www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - ubyte + ubyte = int

reply 0xEAB <desisma heidel.beer> writes:
```d
 safe:

void main()
{
     import std.stdio : writeln;
     writeln(ubyte(4).toHexDigit);
}

ubyte toHexDigit(ubyte decimal) pure nothrow  nogc
{
     if (decimal < 10)
         return (decimal + ubyte('0'));

     if (decimal < 16)
         return (decimal - ubyte(10) + ubyte('A'));

     return '\xFF';
}
```

```
onlineapp.d(12): Error: cannot implicitly convert expression 
`cast(int)decimal + 48` of type `int` to `ubyte`
onlineapp.d(15): Error: cannot implicitly convert expression 
`cast(int)decimal - 10 + 65` of type `int` to `ubyte`
```

I guess, this fancy behavior is inherited from C.

I know this is advanced stuff, but the compiler *could* even 
prove that the calculation(s) won’t go beyond `ubyte.max`.
Oct 26 2022
next sibling parent reply =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/26/22 14:10, 0xEAB wrote:

 I guess, this fancy behavior is inherited from C.
Yes. It is called integer promotions: https://dlang.org/spec/type.html#integer-promotions (The next section is related as well.)
 I know this is advanced stuff, but the compiler *could* even prove that
 the calculation(s) won’t go beyond `ubyte.max`.
Apparently it does not go that far but there is Value Range Propagation: https://www.digitalmars.com/articles/b62.html That article links to this forum post: https://www.digitalmars.com/d/archives/digitalmars/D/Value_Preservation_and_Polysemy_80224.html#N80293 Ali
Oct 26 2022
parent =?UTF-8?Q?Ali_=c3=87ehreli?= <acehreli yahoo.com> writes:
On 10/26/22 14:19, Ali Çehreli wrote:

    https://dlang.org/spec/type.html#integer-promotions
Reading "Value Range Propagation" further down that link, I learned that e.g. masking 'decimal' with 0xf makes the code compile: return ((decimal & 0xf) + ubyte('0')); return ((decimal & 0xf) - ubyte(10) + ubyte('A')); Ali
Oct 26 2022
prev sibling parent reply Salih Dincer <salihdb hotmail.com> writes:
On Wednesday, 26 October 2022 at 21:10:54 UTC, 0xEAB wrote:
 I know this is advanced stuff, but the compiler *could* even 
 prove that the calculation(s) won’t go beyond `ubyte.max`.
 ```d
 //... => char?
         return (decimal - ubyte(10) + ubyte('A'));
 
     return '\xFF';
 }
 ```
You should help the compiler with return type: ```d char toHexDigit(ubyte decimal) pure nothrow nogc { if (decimal < 10) return cast(char) (decimal + ubyte('0')); if (decimal < 16) return cast(char) (decimal - ubyte(10) + ubyte('A')); return '\xFF'; } void main() { import std.stdio : writeln; foreach(ubyte n; 0..256) { const c = n.toHexDigit(); if(n < 16) { c.writeln(": ", n); } else assert(c == char.init); } } /* 0: 0 1: 1 2: 2 3: 3 4: 4 5: 5 6: 6 7: 7 8: 8 9: 9 A: 10 B: 11 C: 12 D: 13 E: 14 F: 15 Process finished. */ ``` SDB 79
Oct 26 2022
parent Salih Dincer <salihdb hotmail.com> writes:
On Thursday, 27 October 2022 at 01:57:15 UTC, Salih Dincer wrote:
 
 You should help the compiler with return type:
I love D, enjoys it when I code...:) I played a little on the code, and the following is possible and beautiful: ```d // If you type auto instead of ubyte as return type, the return will be char. ubyte toHexDigit(bool capital = false)(ubyte decimal) { static if(capital) enum start = 'A'; else enum start = 'a'; if(decimal < 10) return cast(char)(decimal + ubyte('0')); if(decimal < 16) return cast(char)(decimal - ubyte(10) + ubyte(start)); return '\xFF'; } unittest { assert(is(typeof(toHexDigit(9)) == ubyte)); assert(toHexDigit(9) == 57); // '9' assert(toHexDigit(10) == 97); // 'a' assert(toHexDigit!true(10) == 65); // 'A' } ``` SDB 79
Oct 26 2022