Thread overview | |||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
July 26, 2004 DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Cabal | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Arcane Jill | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Daniel Horn | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 Re: DMD 0.96: type not promoting.. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Regan Heath | 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 |
Copyright © 1999-2021 by the D Language Foundation