Jump to page: 1 2
Thread overview
Integer promotion... what I'm missing? (It's monday...)
Jun 19, 2006
Paolo Invernizzi
Jun 19, 2006
Daniel Keep
Jun 19, 2006
Tony
Jun 19, 2006
Lionello Lunesu
Jun 19, 2006
Derek Parnell
Jun 19, 2006
Deewiant
Jun 19, 2006
Paolo Invernizzi
Jun 19, 2006
Tom S
Jun 20, 2006
Derek Parnell
Jun 27, 2006
Alexander Panek
Jun 27, 2006
Kirk McDonald
Jun 28, 2006
Paolo Invernizzi
Jun 28, 2006
Max Samuha
Jun 28, 2006
Kirk McDonald
Jun 28, 2006
Don Clugston
Jun 28, 2006
Paolo Invernizzi
Jun 29, 2006
SwiftCoder
June 19, 2006
Hi all,

What I'm missing?

    uint a = 16;
    int b = -1;
    assert( b < a ); // this fails! I was expecting that -1 < 16

Thanks

---
Paolo
June 19, 2006

Paolo Invernizzi wrote:
> Hi all,
> 
> What I'm missing?
> 
>     uint a = 16;
>     int b = -1;
>     assert( b < a ); // this fails! I was expecting that -1 < 16
> 
> Thanks
> 
> ---
> Paolo

If you read http://digitalmars.com/d/type.html, you will find the rules for integer promotion under arithmetic operations (which I assume also includes comparisons).

Note point 5.4 under "Usual Arithmetic Conversions":

5.4. The signed type is converted to the unsigned type.

Hence, b is being converted to a uint.  cast(uint)(-1) = ~0 = uint.max,
hence why b is not less than a.

If you're going to compare a signed and unsigned type directly, it's best to explicitly cast them to a common type, or strange things like this could happen :)  Either convert a to an int (and watch for overflow), or convert them both to a long (so you don't have problems with overflow).

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
June 19, 2006
"Daniel Keep" <daniel.keep.lists@gmail.com> wrote in message news:e75qg4$2bt$1@digitaldaemon.com...
>
>
> Paolo Invernizzi wrote:
>> Hi all,
>>
>> What I'm missing?
>>
>>     uint a = 16;
>>     int b = -1;
>>     assert( b < a ); // this fails! I was expecting that -1 < 16
>>
>> Thanks
>>
>> ---
>> Paolo
>
> If you read http://digitalmars.com/d/type.html, you will find the rules for integer promotion under arithmetic operations (which I assume also includes comparisons).
>
> Note point 5.4 under "Usual Arithmetic Conversions":
>
> 5.4. The signed type is converted to the unsigned type.
>
> Hence, b is being converted to a uint.  cast(uint)(-1) = ~0 = uint.max,
> hence why b is not less than a.
>
> If you're going to compare a signed and unsigned type directly, it's best to explicitly cast them to a common type, or strange things like this could happen :)  Either convert a to an int (and watch for overflow), or convert them both to a long (so you don't have problems with overflow).
>
> -- Daniel

I believe it is a mistake to have an operation like this occur when it is both mathematically incorrect and unintuitive.  It feels like something that is destined to be a Bug Breeder.

I would prefer that any type promotions (and any implicit operations for that matter) should guarantee not to introduce any data corruption.  In this case, promote both numbers to a third type which can hold all possible values from both.

If the user wishes to override that by making explicit conversions, at least this will be visible in the code.

Tony
Melbourne, Australia



June 19, 2006
Tony wrote:
> I would prefer that any type promotions (and any implicit operations for that matter) should guarantee not to introduce any data corruption.  In this case, promote both numbers to a third type which can hold all possible values from both.

I agree!

Perhaps this could also prevent the "array.length-1" bug (which is ~0 when array.length == 0), by making "array.length-1" a "long" instead of a "uint".

L.
June 19, 2006
On Mon, 19 Jun 2006 20:11:32 +1000, Tony <ignorethis@nowhere.com> wrote:


>> If you read http://digitalmars.com/d/type.html, you will find the rules
>> for integer promotion under arithmetic operations (which I assume also
>> includes comparisons).
>>
>> Note point 5.4 under "Usual Arithmetic Conversions":
>>
>> 5.4. The signed type is converted to the unsigned type.
 . . .

> I believe it is a mistake to have an operation like this occur when it is
> both mathematically incorrect and unintuitive.  It feels like something that is destined to be a Bug Breeder.

No argument from me. This has often caused me grief. The two most often gotchas for me is mismatched template parameters due to this stupid rule, and that array length is a uint which means that all expressions involving array.length get silently converted to uint before the evaluation and that can mess up index accesses.

-- 
Derek Parnell
Melbourne, Australia
June 19, 2006
Tony wrote:
> I would prefer that any type promotions (and any implicit operations for that matter) should guarantee not to introduce any data corruption.  In this case, promote both numbers to a third type which can hold all possible values from both.
> 

What should be done when one number is an ulong too big to fit in a long and the other is a negative number? (Replace "long" with "cent" if we ever get the type.) No matter how the promotion is done, corruption occurs.

I think a warning for all such cases would suffice --- I thought one would be emitted for the original code, but evidently not.
June 19, 2006
Deewiant wrote:
> Tony wrote:
>> I would prefer that any type promotions (and any implicit operations for that matter) should guarantee not to introduce any data corruption.  In this case, promote both numbers to a third type which can hold all possible values from both.
>>
> I think a warning for all such cases would suffice --- I thought one would be
> emitted for the original code, but evidently not.

Instead of a warning, I would prefer an error, forcing for an explicit cast if the comparison it's what you really want to to. But only for rule number 4.

Cheers

---
Paolo
June 19, 2006
Paolo Invernizzi wrote:
> Instead of a warning, I would prefer an error, forcing for an explicit cast if the comparison it's what you really want to to. But only for rule number 4.

I'd also like DMD to issue an error in this case, as I've stumbled upon it a few times.


-- 
Tomasz Stachowiak  /+ a.k.a. h3r3tic +/
June 20, 2006
On Tue, 20 Jun 2006 04:06:37 +0200, Paolo Invernizzi wrote:

> Deewiant wrote:
>> Tony wrote:
>>> I would prefer that any type promotions (and any implicit operations for that matter) should guarantee not to introduce any data corruption.  In this case, promote both numbers to a third type which can hold all possible values from both.
>>>
>> I think a warning for all such cases would suffice --- I thought one would be emitted for the original code, but evidently not.
> 
> Instead of a warning, I would prefer an error, forcing for an explicit cast if the comparison it's what you really want to to. But only for rule number 4.
> 

Just to note that with DMD, a 'warning' is really an optional error. In other words, if you have -w switch and it displays a 'warning', the compiler still fails to create the object file because it treats such warnings as if they were errors.

-- 
Derek
(skype: derek.j.parnell)
Melbourne, Australia
"Down with mediocrity!"
20/06/2006 11:04:06 AM
June 27, 2006
If you take a look at how comparison works, you'll know why this one fails.

Lets take an uint a = 16; as in your example:
00000000 00000000 00000000 00010000

And now a signed integer with the value -1:
10000000 00000000 00000000 00000001

You might guess which number is bigger, when our comparison is done binary (and after all, that's what the processor does) :)

Regards,
Alex

Paolo Invernizzi wrote:
> Hi all,
> 
> What I'm missing?
> 
>     uint a = 16;
>     int b = -1;
>     assert( b < a ); // this fails! I was expecting that -1 < 16
> 
> Thanks
> 
> ---
> Paolo
« First   ‹ Prev
1 2