Jump to page: 1 2
Thread overview
DMD 0.96: type not promoting..
Jul 26, 2004
Regan Heath
Jul 26, 2004
Regan Heath
Jul 26, 2004
Cabal
Jul 26, 2004
Regan Heath
Jul 26, 2004
Daniel Horn
Jul 27, 2004
Regan Heath
Jul 27, 2004
Arcane Jill
Jul 27, 2004
Derek Parnell
Jul 27, 2004
Regan Heath
Jul 27, 2004
Regan Heath
Jul 26, 2004
Arcane Jill
Jul 26, 2004
Regan Heath
Jul 27, 2004
Walter
July 26, 2004
Hi,

I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise.

import std.string;

void output(long a)
{
  printf("%.*s\n",toString(a));
}

void main()
{
  long a,b;

  //inline
  output(int.max+1);

  //using long
  a = int.max+1;
  output(a);

  //using constant value
  output(2147483647+1);

  //using long in 2 steps
  b = int.max;
  b += 1;
  output(b);
}

Ouput:
-2147483648
-2147483648
-2147483648
2147483648

The last result was the desired result in my case. I believe all 4 tests should give that result.


The C equivalent, using short as C does not have a long (that is bigger than an int) and assuming that the D property is an int itself, which it seems to be, would be:

#include <limits.h>

void foo(int a) {
  printf("%d\n",a);
}
void main() {
  short max = SHRT_MAX;
  int a,b;

  //inline
  output(max+1);

  //using int
  a = max+1;
  output(a);

  //using constant value
  output(32767+1);

  //using int in 2 steps
  b = max;
  b += 1;
  output(b);
}

Output:
32768
32768
32768
32768

So it appears C is promoting the short 'a' to an int then adding 1 to it _or_ perhaps this is all due to how int and short are physically represented?

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 26, 2004
I just tried it D with int and short, eg.

import std.string;

void output(int a)
{
  printf("%.*s\n",toString(a));
}

void main()
{
  int a,b;

  //inline
  output(short.max+1);

  //using var
  a = short.max+1;
  output(a);

  //using constant value
  output(32767+1);

  //2 steps
  b = short.max;
  b += 1;
  output(b);
}

Output:
32768
32768
32768
32768

So it appears the behaviour is different when using int/short to long/int.

Regan

On Mon, 26 Jul 2004 20:06:59 +1200, Regan Heath <regan@netwin.co.nz> wrote:
> Hi,
>
> I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise.
>
> import std.string;
>
> void output(long a)
> {
>    printf("%.*s\n",toString(a));
> }
>
> void main()
> {
>    long a,b;
>
>    //inline
>    output(int.max+1);
>
>    //using long
>    a = int.max+1;
>    output(a);
>
>    //using constant value
>    output(2147483647+1);
>
>    //using long in 2 steps
>    b = int.max;
>    b += 1;
>    output(b);
> }
>
> Ouput:
> -2147483648
> -2147483648
> -2147483648
> 2147483648
>
> The last result was the desired result in my case. I believe all 4 tests should give that result.
>
>
> The C equivalent, using short as C does not have a long (that is bigger than an int) and assuming that the D property is an int itself, which it seems to be, would be:
>
> #include <limits.h>
>
> void foo(int a) {
>    printf("%d\n",a);
> }
> void main() {
>    short max = SHRT_MAX;
>    int a,b;
>
>    //inline
>    output(max+1);
>
>    //using int
>    a = max+1;
>    output(a);
>
>    //using constant value
>    output(32767+1);
>
>    //using int in 2 steps
>    b = max;
>    b += 1;
>    output(b);
> }
>
> Output:
> 32768
> 32768
> 32768
> 32768
>
> So it appears C is promoting the short 'a' to an int then adding 1 to it _or_ perhaps this is all due to how int and short are physically represented?
>
> Regan
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 26, 2004
I would regard your first example as correct and the second as a bug in D.

>   //inline
>   output(int.max+1);
>
>   //using long
>   a = int.max+1;
>   output(a);
>
>   //using constant value
>   output(2147483647+1);

In these lines you are adding 1 to int.max in an integer context which trips over into negative values. Only after this has happened is the int promoted to a long, and so the long contains a negative value too.

Your second example looks like D is actually doing its short arithmetic with integer types. Which would be wrong imo.
July 26, 2004
In article <opsbqjhxmf5a2sq9@digitalmars.com>, Regan Heath says...
>
>Hi,
>
>I just got bitten by a type promotion problem, I was wondering whether people here think this is a bug, or otherwise.

I suspect it's probably not a bug, but defined behaviour. From "Lexical":

The type of the integer is resolved as follows:

1. If it is decimal it is the last representable of ulong, long, or int.
2. If it is not decimal, it is the last representable of ulong, long, uint, or
int.
3. If it has the 'u' suffix, it is the last representable of ulong or uint.
4. If it has the 'l' suffix, it is the last representable of ulong or long.
5. If it has the 'u' and 'l' suffixes, it is ulong.


So, I guess what you need to do is one of:
#    cast(long) int.max;
#    4294967295l; // That's a lowercase L at the end, not a digit one.


July 26, 2004
On Mon, 26 Jul 2004 09:56:15 +0100, Cabal <cabalN05P4M@myrealbox.com> wrote:
> I would regard your first example as correct and the second as a bug in D.
>
>>    //inline
>>    output(int.max+1);
>>
>>    //using long
>>    a = int.max+1;
>>    output(a);
>>
>>    //using constant value
>>    output(2147483647+1);
>
> In these lines you are adding 1 to int.max in an integer context which trips
> over into negative values. Only after this has happened is the int promoted
> to a long, and so the long contains a negative value too.

I assumed that is what was happening. Changing this:
>>    //using constant value
>>    output(2147483647+1);
to:
>>    //using constant value
>>    output(2147483647L+1);

also gives me what I want "2147483648", instead of "-2147483648", I guess one has to remember that constants in D are integers, unless you state otherwise.

> Your second example looks like D is actually doing its short arithmetic with
> integer types. Which would be wrong imo.

This example behaves as C/C++ does. I assume because:
 - short.max is actually an 'int' not a 'short'.
 - the constant is assumed to be an int.

If short.max was a 'short' then my first trials would have given negative values and the last 2 positive values.


How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour.

It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg.

float a;
int b;

a = b/100;

if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as:

a = cast(float)b/cast(float)100;

or perhaps

a = cast(float)b/100.0;

I would argue the more common intent should be the default behaviour.

Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?

How does Java handle this sort of thing? What about python or Ruby?

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 26, 2004
On Mon, 26 Jul 2004 11:50:23 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:

> In article <opsbqjhxmf5a2sq9@digitalmars.com>, Regan Heath says...
>>
>> Hi,
>>
>> I just got bitten by a type promotion problem, I was wondering whether
>> people here think this is a bug, or otherwise.
>
> I suspect it's probably not a bug, but defined behaviour. From "Lexical":
>
> The type of the integer is resolved as follows:
>
> 1. If it is decimal it is the last representable of ulong, long, or int.
> 2. If it is not decimal, it is the last representable of ulong, long, uint, or
> int.
> 3. If it has the 'u' suffix, it is the last representable of ulong or uint.
> 4. If it has the 'l' suffix, it is the last representable of ulong or long.
> 5. If it has the 'u' and 'l' suffixes, it is ulong.

I figured that might be the case. Thanks for the above, I didn't find it in my searching.

> So, I guess what you need to do is one of:
> #    cast(long) int.max;
> #    4294967295l; // That's a lowercase L at the end, not a digit one.

Uppercase L works too, and is easier to see.

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 26, 2004
Python just changed their language to do automatic type promotion
I hate it! :-(
if you divide 2 integers you wish to do integer math, not float math... (think arrays,random numbers, etc..)

Also it's a lot slower to start using the greatest possible type your expression could produce.  If you wish this behavior, write a class to do it (see: Arcane Jill's Big Integer)
:-)
or else just do math on longs, or reals all the time, rather than using smaller types initially.



> How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour.
> 
> It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg.
> 
> float a;
> int b;
> 
> a = b/100;
> 
> if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as:
> 
> a = cast(float)b/cast(float)100;
> 
> or perhaps
> 
> a = cast(float)b/100.0;
> 
> I would argue the more common intent should be the default behaviour.
> 
> Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?
> 
> How does Java handle this sort of thing? What about python or Ruby?
> 
> Regan.
> 
July 27, 2004
On Mon, 26 Jul 2004 16:55:05 -0700, Daniel Horn <hellcatv@hotmail.com> wrote:
> Python just changed their language to do automatic type promotion
> I hate it! :-(
> if you divide 2 integers you wish to do integer math, not float math... (think arrays,random numbers, etc..)

and you will do integer math with my suggestion as long as you assign the result to an int and not a float... IIRC python does not have clearly defined types, so they cannot make this decision, yes?

> Also it's a lot slower to start using the greatest possible type your expression could produce.

That is not the behaviour I want. What I want is the operands to be cast to the result type _before_ the expression is evaluated, rather than the current behaviour which is to cast the result after the expression.

> If you wish this behavior, write a class to do it (see: Arcane Jill's Big Integer)
> :-)
> or else just do math on longs, or reals all the time, rather than using smaller types initially.
>
>
>
>> How bout this for a radical new idea, I realise it would cause behaviour changes from C to D for the same expression, why not promote all operands in an expression to the resulting type, forcing people to use a cast if they do not want that behaviour.
>>
>> It occurs to me that wanting this behaviour is more common than wanting the current behaviour. eg.
>>
>> float a;
>> int b;
>>
>> a = b/100;
>>
>> if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as:
>>
>> a = cast(float)b/cast(float)100;
>>
>> or perhaps
>>
>> a = cast(float)b/100.0;
>>
>> I would argue the more common intent should be the default behaviour.
>>
>> Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?
>>
>> How does Java handle this sort of thing? What about python or Ruby?
>>
>> Regan.
>>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 27, 2004
D cares along wholesale the C/C++ rules on integral promotions in arithmetic expressions, which is what you're seeing. Changing this would mean very subtle problems will crop up when converting C/C++ code into D, something I think is worse.


July 27, 2004
In article <opsbrqxd1l5a2sq9@digitalmars.com>, Regan Heath says...

>the current behaviour. eg.
>
>float a;
>int b;
>
>a = b/100;
>
>if 'b' and '100' are promoted to float before the calculation you get a different answer, and it's the answer you actually wanted in most cases. Currently you have to write the above as:
>
>a = cast(float)b/cast(float)100;
>
>or perhaps
>
>a = cast(float)b/100.0;
>
>I would argue the more common intent should be the default behaviour.

Are you sure about D's current behavior. The way I read it, it currently does exactly what you want. From the manual:

"The usual arithmetic conversions convert operands of binary operators to a common type. The operands must already be of arithmetic types. The following rules are applied in order:

1. Typedefs are converted to their underlying type.
2. If either operand is real, the other operand is converted to real.
3. Else if either operand is double, the other operand is converted to double.
4. Else if either operand is float, the other operand is converted to float.
5. Else the integer promotions are done on each operand, followed by:
1. If both are the same type, no more conversions are done.
2. If both are signed or both are unsigned, the smaller type is converted to the
larger.
3. If the signed type is larger than the unsigned type, the unsigned type is
converted to the signed type.
4. The signed type is converted to the unsigned type."


Obviously, if it's not doing this, it's a bug, but it's always seemed to work for me.


>Can anyone think of a counter example that shows a commonly desired outcome that is the current default behaviour?

I'm not convinced that /is/ the current default behavior. D works the same way as C and C++.



>How does Java handle this sort of thing? What about python or Ruby?

I think Java /also/ works the same way as C, C++ and D (except that Java doesn't have unsigned types apart from char).

Can't speak for those languages, but I can tell you that PHP is really weird. It expands numbers as required, like Python, and doesn't have unsigned types, so the constant 0xFFFFFFFF is a /double/. Actually I don't like this.

Jill


« First   ‹ Prev
1 2