April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" <derek@psych.ward> wrote in message news:eouhnxxkjb80$.clvse1356mlr.dlg@40tude.net... > There seems to be different treatment of literals and variables. No, there isn't. The reason for the difference is when you assign the literal to z. Use the 'L' suffix for a real literal. |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | On Fri, 1 Apr 2005 18:50:40 -0800, Walter wrote: > "Derek Parnell" <derek@psych.ward> wrote in message news:eouhnxxkjb80$.clvse1356mlr.dlg@40tude.net... >> There seems to be different treatment of literals and variables. > > No, there isn't. The reason for the difference is when you assign the literal to z. Use the 'L' suffix for a real literal. Ok, I did that. And I still can't explain the output. Raw Floor Using float variable: 0x1.3fffff4afp+4 0x1.3p+4 Using double variable: 0x1.4p+4 0x1.3p+4 Using real variable: 0x1.4000000000000002p+4 0x1.4p+4 Using float literal: 0x1.3fffff4afp+4 0x1.4p+4 Using double literal: 0x1.4p+4 0x1.4p+4 Using real literal: 0x1.4000000000000002p+4 0x1.4p+4 Look at the results for doubles. How does floor(0x1.4p+4) give 0x1.3p+4 when the expression is a variable and give 0x1.4p+4 when the expression is a literal? -- Derek Parnell Melbourne, Australia 2/04/2005 3:34:22 PM |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | On Sat, 2 Apr 2005 15:39:01 +1000, Derek Parnell wrote:
I've reformatted the display to make it easier to spot the anomaly.
Raw Floor
Using float variable: 0x1.3fffff4afp+4 0x1.3p+4
Using float literal: 0x1.3fffff4afp+4 0x1.4p+4
Using double variable: 0x1.4p+4 0x1.3p+4 Using double literal: 0x1.4p+4 0x1.4p+4
Using real variable: 0x1.4000000000000002p+4 0x1.4p+4 Using real literal: 0x1.4000000000000002p+4 0x1.4p+4
And here is the program that created the above ...
<code>
import std.stdio;
import std.math;
import std.string;
void main() {
float x;
double y;
real z;
x = 0.0000195F;
y = 0.0000195;
z = 0.0000195L;
writefln(" %24s %24s","Raw","Floor");
writefln("Using float variable: %24a %24a",
(.5 + 1e6*x), floor(.5 + 1e6*x));
writefln("Using float literal: %24a %24a",
(.5 + 1e6*0.0000195f), floor(.5 + 1e6*0.0000195f));
writefln("");
writefln("Using double variable: %24a %24a",
(.5 + 1e6*y), floor(.5 + 1e6*y));
writefln("Using double literal: %24a %24a",
(.5 + 1e6*0.0000195), floor(.5 + 1e6*0.0000195));
writefln("");
writefln("Using real variable: %24a %24a",
(.5 + 1e6*z), floor(.5 + 1e6*z));
writefln("Using real literal: %24a %24a",
(.5 + 1e6*0.0000195l), floor(.5 + 1e6*0.0000195l));
}
</code>
--
Derek Parnell
Melbourne, Australia
2/04/2005 4:48:12 PM
|
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" <derek@psych.ward> wrote in message news:124cwpdauczht$.1wqi8sqkdi4ec.dlg@40tude.net... > Ok, I did that. And I still can't explain the output. Recall that, at runtime, the intermediate values are allowed to be carried out to 80 bits. So, floor(.5 + 1e6*y) is evaluated as: floor(cast(real).5 + cast(real)(1e6) * cast(real)y); whereas: floor(.5 + 1e6*0.0000195) is evaluated as: float(cast(real)(.5 + 1e6*0.0000195)) hence the difference in result. |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | I have started a new thread: "80 Bit Challenge", which should serve as a reply to your post .... |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <newshound@digitalmars.com> wrote in message news:d2lodh$2qhf$1@digitaldaemon.com... > > "Derek Parnell" <derek@psych.ward> wrote in message news:124cwpdauczht$.1wqi8sqkdi4ec.dlg@40tude.net... >> Ok, I did that. And I still can't explain the output. > > Recall that, at runtime, the intermediate values are allowed to be carried out to 80 bits. So, > > floor(.5 + 1e6*y) > > is evaluated as: > > floor(cast(real).5 + cast(real)(1e6) * cast(real)y); > > whereas: > > floor(.5 + 1e6*0.0000195) > > is evaluated as: > > float(cast(real)(.5 + 1e6*0.0000195)) > > hence the difference in result. > It's C legacy hidden in the way the compiler parses this code. You'll be facing these kind of questions over and over again, unless you move a step further away from C and let the compiler treat unsuffixed literals as the "internal compiler floating point precision format". See my thread: "80 Bit Challenge" |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | On Sat, 2 Apr 2005 01:23:46 -0800, Walter wrote: > "Derek Parnell" <derek@psych.ward> wrote in message news:124cwpdauczht$.1wqi8sqkdi4ec.dlg@40tude.net... >> Ok, I did that. And I still can't explain the output. > > Recall that, at runtime, the intermediate values are allowed to be carried out to 80 bits. So, > > floor(.5 + 1e6*y) > > is evaluated as: > > floor(cast(real).5 + cast(real)(1e6) * cast(real)y); > > whereas: > > floor(.5 + 1e6*0.0000195) > > is evaluated as: > > float(cast(real)(.5 + 1e6*0.0000195)) > > hence the difference in result. Got it. So to summarize, in expressions that contain at least one double variable, each term is promoted to real before expression evaluation, but if the expression only contains double literals, then the terms are not promoted to real. Why did you decide to have this anomaly? -- Derek Parnell Melbourne, Australia 2/04/2005 11:46:44 PM |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" <derek@psych.ward> wrote in message news:lsphadeuh4s3.gjqbum65kx87$.dlg@40tude.net... > So to summarize, in expressions that contain at least one double variable, each term is promoted to real before expression evaluation, but if the expression only contains double literals, then the terms are not promoted to real. > > Why did you decide to have this anomaly? It's the way C works. |
April 02, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | On Sat, 2 Apr 2005 10:04:32 -0800, Walter wrote: > "Derek Parnell" <derek@psych.ward> wrote in message news:lsphadeuh4s3.gjqbum65kx87$.dlg@40tude.net... >> So to summarize, in expressions that contain at least one double variable, each term is promoted to real before expression evaluation, but if the expression only contains double literals, then the terms are not promoted to real. >> >> Why did you decide to have this anomaly? > > It's the way C works. I understand. And here I was thinking that D was meant to be better than C. My bad. -- Derek Parnell Melbourne, Australia 3/04/2005 8:13:09 AM |
April 03, 2005 Re: Exotic floor() function - D is different | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek Parnell | "Derek Parnell" <derek@psych.ward> wrote in message news:lsphadeuh4s3.gjqbum65kx87$.dlg@40tude.net... > On Sat, 2 Apr 2005 01:23:46 -0800, Walter wrote: > >> "Derek Parnell" <derek@psych.ward> wrote in message news:124cwpdauczht$.1wqi8sqkdi4ec.dlg@40tude.net... >>> Ok, I did that. And I still can't explain the output. >> >> Recall that, at runtime, the intermediate values are allowed to be >> carried >> out to 80 bits. So, >> >> floor(.5 + 1e6*y) >> >> is evaluated as: >> >> floor(cast(real).5 + cast(real)(1e6) * cast(real)y); >> >> whereas: >> >> floor(.5 + 1e6*0.0000195) >> >> is evaluated as: >> >> float(cast(real)(.5 + 1e6*0.0000195)) >> >> hence the difference in result. > > Got it. > > So to summarize, in expressions that contain at least one double variable, each term is promoted to real before expression evaluation, but if the expression only contains double literals, then the terms are not promoted to real. > > Why did you decide to have this anomaly? > > -- > Derek Parnell > Melbourne, Australia > 2/04/2005 11:46:44 PM Some further info: Currently it seems that in the D language no literal is ever promoted to real directly if it was not suffixed with a "L". You can cast(real) it, and it will still be a double which is converted to a crippled real in the FPU, because some of its matissa bits went missing. There are many exceptions though: All floating point integers (1.0 2.0 10.0 etc.) and fractions like 0.5 0.25 0.125 etc. are converted to proper real values, because they are accurately represented in binary floating point formats. But even they are initially doubles, which are just unharmed by the conversion because most of their trailing mantissa bits are zero. Any other fractional number (e.g. 1.2) cannot be represented accurately in the binary system, so its double representation is not equivalent to its real representation (nor is it to the decimal literal). If such a double is converted to real, it is missing several bits of precision, so it will not correspond accurately to its properly converted counterpart (e.g. 1.2L). As a summary: If you feel the need using extended double (real) precision in D, never ever forget the "L" for literals unless you want "special effects". Examples: real r=1.2L; // proper 80 bit real assigned to r real r=1.2; // inaccurate truncated 80 bit real real r=2.4/2.0; // inaccurate (2.4 loses precision) real r=2.4/2.0L; // inaccurate for the same reason real r=2.4L/2.0; // this one will work (2.0 == 2.0L) real r=2.4L/2.0L; // thats the safe way to do it real r=cast(real)1.2; // inaccurate, converted from // 1.2 as a double By the way, C does it the same way for historic reasons. Other languages are more user friendly and I am still hoping that D might evolve in this direction. |
Copyright © 1999-2021 by the D Language Foundation