Bug 45 – Bug in conversion of floating point literals
Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D1 (retired)
Platform
x86
OS
Windows
Creation time
2006-03-13T06:52:00Z
Last change time
2014-02-15T02:09:22Z
Assigned to
bugzilla
Creator
clugdbug
Comments
Comment #0 by clugdbug — 2006-03-13T06:52:31Z
Literals are treated (incorrectly) as type real when used in an initialiser, but as type double when used in an assignment. This is an extremely difficult bug to track down, as it is essentially bad code generation, so I've marked it as critical.
void main()
{
real a = 3.40483; // this is treated as 3.40483L
real b;
b = 3.40483;
assert(a==b);
}
Comment #1 by thomas-dloop — 2006-03-15T05:10:23Z
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
[email protected] schrieb am 2006-03-13:
> Literals are treated (incorrectly) as type real when used in an initialiser,
> but as type double when used in an assignment. This is an extremely difficult
> bug to track down, as it is essentially bad code generation, so I've marked it
> as critical.
>
> void main()
> {
> real a = 3.40483; // this is treated as 3.40483L
> real b;
> b = 3.40483;
> assert(a==b);
> }
Strictly speaking the code above behaves correctly.
http://www.digitalmars.com/d/float.html
# For floating point operations and expression intermediate values, a
# greater precision can be used than the type of the expression. Only the
# minimum precision is set by the types of the operands, not the maximum.
The documentation doesn't require an expression to always use the same
"excessive" precision.
Never the less, the shown behaviour is annoying - either expand the
literal's precision on all ocasion or never.
Thomas
-----BEGIN PGP SIGNATURE-----
iD8DBQFEGALe3w+/yD4P9tIRArsSAKCYGMgpxTsDAS+JjXovgDLk3gu0KQCg0gIL
rV7NfmeNKjFgjvCAGKwfUqw=
=wbYB
-----END PGP SIGNATURE-----
Comment #2 by clugdbug — 2006-03-15T06:12:05Z
> Strictly speaking the code above behaves correctly.
>
> http://www.digitalmars.com/d/float.html
> # For floating point operations and expression intermediate values, a
> # greater precision can be used than the type of the expression. Only the
> # minimum precision is set by the types of the operands, not the maximum.
>
> The documentation doesn't require an expression to always use the same
> "excessive" precision.
That doesn't apply in this case. There's no intermediate value here.
3.40483L is not the same as 3.40483. It's a different number.
You provide the compiler with input values of a given precision, and it returns output values of a different precision. It's free to use any higher precision during the intermediate calculations, but it is NOT free to change the precision of the inputs (if it were, the L prefix would be entirely meaningless). It's just a bug (and I suspect it's a regression introduced during the improvements to constant folding that occurred around DMD 0.138).
Comment #3 by thomas-dloop — 2006-03-15T14:30:28Z
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
[email protected] schrieb am 2006-03-15:
>> Strictly speaking the code above behaves correctly.
>>
>> http://www.digitalmars.com/d/float.html
>> # For floating point operations and expression intermediate values, a
>> # greater precision can be used than the type of the expression. Only the
>> # minimum precision is set by the types of the operands, not the maximum.
>>
>> The documentation doesn't require an expression to always use the same
>> "excessive" precision.
>
> That doesn't apply in this case. There's no intermediate value here.
>
> 3.40483L is not the same as 3.40483. It's a different number.
>
> You provide the compiler with input values of a given precision, and it returns
> output values of a different precision. It's free to use any higher precision
> during the intermediate calculations, but it is NOT free to change the
> precision of the inputs (if it were, the L prefix would be entirely
> meaningless). It's just a bug (and I suspect it's a regression introduced
> during the improvements to constant folding that occurred around DMD 0.138).
I'm deffinatly on the "literal defines precision" side, but have a look
at:
http://d.puremagic.com/bugzilla/show_bug.cgi?id=21
Thomas
-----BEGIN PGP SIGNATURE-----
iD8DBQFEGIMR3w+/yD4P9tIRAkJqAKCHk1V4EB/gmrpgUQnXKp86YQMlWQCgl0SD
fdSYAXNs3CxYxIcsIeze+yo=
=mefP
-----END PGP SIGNATURE-----
Comment #4 by clugdbug — 2006-03-16T02:16:51Z
(In reply to comment #3)
> I'm deffinatly on the "literal defines precision" side, but have a look
> at:
> http://d.puremagic.com/bugzilla/show_bug.cgi?id=21
In his reply to that comment, Walter states:
"D always tries to do any compile time evaluation of floating
point constants at max precision."
That's perfectly reasonable, too. But it means that there's still a bug, but it's a different one now: floating point constants are not evaluated at max precision in assignment statements. But there's definitely something weird going on. Apparently, const double doesn't exist.
const float f = real.max;
real r = f;
This sets r = real.max. That's incredible, because a number that large cannot be stored in a float. If this behaviour is to remain, then 'const float' and 'const double' should be removed from the language, along with the 'f' and 'L' suffixes : all floating point constants are real.
However,
real r2;
r2 = f;
sets r2 = real.inf, which is what I would expect - real.max can't be stored in a float, so it became an infinity.