July 27, 2004
On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill wrote:

> 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.

It is doing this, but this is not what is wanted by Regan. The expression 'a = b/100' is probable assessed thus ...

**    b is an int. 100 is an int. Rule 5 applies. They remain 'int' as they
are the same size integer. Thus the result of the calculation is an int
too.
**    a is a float, result is an int. Rule 4 applies. The result is
converted to a float. The answer (assignment) is a float. But, not the
expected value. It gets truncated to an int prior to conversion to a float.


Maybe a better way would be for the compiler to recognize that the coder is asking for an assignment to a float, so all left-hand expressions need to be at least a float, but possibly promoted to real during calculation then truncated to float on assignment.

If the coder wishes to cause the resulting left hand expression to be truncated to an integer, she could use an explicit cast.

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

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

Calculating pixel positions need to be truncated to integer values.

> 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).

The Euphoria language does it the way Regan wants...

 c:\temp>type test.ex

    atom a
    integer b
    b = 3335
    a = b / 100
    printf(1, "%f\n", a)

 c:\temp>ex test
 33.350000

 c:\temp>

And D definitely does not ...

c:\temp>type test.d
 import std.stdio;
 void main()
 {
    float a;
    int b;
    b = 3335;
    a = b / 100;
    writef("%f\n", a);
 }
 c:\temp>dmd test
 C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;

 c:\temp>test
 33.000000

 c:\temp>

But if you make one tiny change, one gets ...

 c:\temp>type test.d
 import std.stdio;
 void main()
 {
    float a;
    int b;
    b = 3335;
    a = b / 100.0;  // <-- Explicit float literal
    writef("%f\n", a);
 }
 c:\temp>dmd test
 C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;

 c:\temp>test
 33.349998

 c:\temp>

Well almost, the precision isn't so hot. To get better, change 'a' to double or real.


-- 
Derek
Melbourne, Australia
27/Jul/04 6:10:32 PM
July 27, 2004
On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill <Arcane_member@pathlink.com> wrote:
> 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.

I assumed it was the same as C/C++.

> 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.

These rules do not help for:
  a = b/100
(if a is a float and b is an int)

they do help for:
  a = b/100   (if b is a float)
  a = b/100.0 (as 100.0 is a float)

maybe it's just me, I do not think "100.0" when I think "one hundred" I think of "100" so I'll write "100", and it will give the wrong result.

>> 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++.

The problem I have mentioned _is_ one I have in 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.

I don't want types to be expanded, why does everyone think that is what I am after...

"type expansion", to me, suggests making an 'int' into a 'long' because the value assigned to it is too big for an 'int', I don't want that at all.

I simply want the type promotion it would do to the result to be done to the operands before the expression is evaluated. eg.

float a;
int b;

a = b/100

causes:
- b is promoted to float
- 100 is promoted to float
- expression evaluated
- result assigned to a;

Yes, this causes more promotions to be done.
Yes, this changes the result of the expression, such that in C it would give a different result.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 27, 2004
On Tue, 27 Jul 2004 18:32:28 +1000, Derek Parnell <derek@psych.ward> wrote:
> On Tue, 27 Jul 2004 07:46:07 +0000 (UTC), Arcane Jill wrote:
>
>> 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.
>
> It is doing this, but this is not what is wanted by Regan. The expression
> 'a = b/100' is probable assessed thus ...
>
> **    b is an int. 100 is an int. Rule 5 applies. They remain 'int' as they
> are the same size integer. Thus the result of the calculation is an int
> too.
> **    a is a float, result is an int. Rule 4 applies. The result is
> converted to a float. The answer (assignment) is a float. But, not the
> expected value. It gets truncated to an int prior to conversion to a float.

Exactly! I didn't think I had to spell this out, obviously this mistake/bug/problem is not as comman as I thought, I have had it numerous times.

> Maybe a better way would be for the compiler to recognize that the coder is
> asking for an assignment to a float, so all left-hand expressions need to
> be at least a float, but possibly promoted to real during calculation then
> truncated to float on assignment.

That is what I have been suggesting.

> If the coder wishes to cause the resulting left hand expression to be
> truncated to an integer, she could use an explicit cast.
>
>    float a;
>    int b;
>    a = cast(int)(b/100);

Yep.

>>> Can anyone think of a counter example that shows a commonly desired
>>> outcome that is the current default behaviour?
>
> Calculating pixel positions need to be truncated to integer values.

The key word in my request was "commonly", I do not believe the above to be common. So while it's a good example that it needs to be possible, it's not the commonly desired outcome, and in fact if you were doing the above you'd remember to ensure it happens, correct?

>> 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).
>
> The Euphoria language does it the way Regan wants...
>
>  c:\temp>type test.ex
>
>     atom a
>     integer b
>     b = 3335
>     a = b / 100
>     printf(1, "%f\n", a)
>
>  c:\temp>ex test
>  33.350000
>
>  c:\temp>
>
> And D definitely does not ...
>
> c:\temp>type test.d
>  import std.stdio;
>  void main()
>  {
>     float a;
>     int b;
>     b = 3335;
>     a = b / 100;
>     writef("%f\n", a);
>  }
>  c:\temp>dmd test
>  C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;
>
>  c:\temp>test
>  33.000000
>
>  c:\temp>
>
> But if you make one tiny change, one gets ...
>
>  c:\temp>type test.d
>  import std.stdio;
>  void main()
>  {
>     float a;
>     int b;
>     b = 3335;
>     a = b / 100.0;  // <-- Explicit float literal
>     writef("%f\n", a);
>  }
>  c:\temp>dmd test
>  C:\DPARNELL\DMD\BIN\..\..\dm\bin\link.exe test,,,user32+kernel32/noi;
>
>  c:\temp>test
>  33.349998
>
>  c:\temp>
>
> Well almost, the precision isn't so hot. To get better, change 'a' to
> double or real.

Good examples. Thanks.

Regan

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
1 2
Next ›   Last »