Re: formatting a float or double in a string with all significant digits kept

2019-10-10 Thread dan via Digitalmars-d-learn

On Thursday, 10 October 2019 at 22:44:05 UTC, H. S. Teoh wrote:
On Thu, Oct 10, 2019 at 09:13:05PM +, Jon Degenhardt via 
Digitalmars-d-learn wrote:

On Thursday, 10 October 2019 at 17:12:25 UTC, dan wrote:
> Thanks also berni44 for the information about the dig 
> attribute, Jon
> for the neat packaging into one line using the attribute on 
> the

> type.
> Unfortunately, the version of gdc that comes with the 
> version of
> debian that i am using does not have the dig attribute yet, 
> but
> perhaps i can upgrade, and eventually i think gdc will have 
> it.


What's the output of dmd --version?  I find it extremely odd 
that .dig isn't supported.  AFAIK, it's been there since the 
early days of D. Certainly, it has been there since I started 
using D, which was before dmd was ever available in Debian.


What's the compiler output of:

pragma(msg, float.dig);

?


T


Thanks HS!

I sure thought i got a compile time error when i used .dig, but i 
tried

it again, and it works.

I tried the pragma, and it printed out 6, and i tried PI.dig and 
double.dig

and they're all working now.

Just for reference, i'm using what i think is the standard gdc on 
debian 9,

not dmd, and the version is 2068L.

Thanks again for your help in encouraging me to try harder, and 
thanks again

everybody else for all the help.

dan








Re: formatting a float or double in a string with all significant digits kept

2019-10-10 Thread H. S. Teoh via Digitalmars-d-learn
On Thu, Oct 10, 2019 at 09:13:05PM +, Jon Degenhardt via 
Digitalmars-d-learn wrote:
> On Thursday, 10 October 2019 at 17:12:25 UTC, dan wrote:
> > Thanks also berni44 for the information about the dig attribute, Jon
> > for the neat packaging into one line using the attribute on the
> > type.
> > Unfortunately, the version of gdc that comes with the version of
> > debian that i am using does not have the dig attribute yet, but
> > perhaps i can upgrade, and eventually i think gdc will have it.

What's the output of dmd --version?  I find it extremely odd that .dig
isn't supported.  AFAIK, it's been there since the early days of D.
Certainly, it has been there since I started using D, which was before
dmd was ever available in Debian.

What's the compiler output of:

pragma(msg, float.dig);

?


T

-- 
Many open minds should be closed for repairs. -- K5 user


Re: formatting a float or double in a string with all significant digits kept

2019-10-10 Thread Jon Degenhardt via Digitalmars-d-learn

On Thursday, 10 October 2019 at 17:12:25 UTC, dan wrote:

Thanks also berni44 for the information about the dig attribute,
Jon for the neat packaging into one line using the attribute on 
the type.
Unfortunately, the version of gdc that comes with the version 
of debian
that i am using does not have the dig attribute yet, but 
perhaps i can

upgrade, and eventually i think gdc will have it.


Glad these ideas helped. The value of the 'double.dig' property 
is not going to change between compilers/versions/etc. It's 
really a property of IEEE 754 floating point for 64 bit floats. 
(D specified the size of double as 64).  So, if you are using 
double, then it's pretty safe to use 15 until the compiler you're 
using is further along on versions. Declare an enum or const 
variable to give it a name so you can track it down later.


Also, don't get thrown off by the PI is a real, not a double. D 
supports 80 bit floats as real, so constants like PI are defined 
as real. But if you convert PI to a double, it'll then have 15 
significant bits of precision.


--Jon


Re: formatting a float or double in a string with all significant digits kept

2019-10-10 Thread dan via Digitalmars-d-learn

On Wednesday, 9 October 2019 at 10:54:49 UTC, David Briant wrote:

On Tuesday, 8 October 2019 at 20:37:03 UTC, dan wrote:
I have a double precision number that i would like to print 
all significant digits of, but no more than what are actually 
present in the number.  Or more exactly, i want to print the 
minimum number of digits necessary to recover the original 
number to within 2 or 3 least significant bits in the stored, 
in-core, version of its bit pattern.


For example,


import std.string;
import std.stdio;
import std.math;

void main( ) {
  auto t = format("%3.30f", PI );
  writeln("Value of PI is: ", PI, " or, : ", t);
}

The default way writeln prints is 5 digits to the right of the 
decimal point.


I can format to print with any number of digits, such as 30 
above, but that's too many.


For pi, the correct number of digits to print looks to be 
about 18 (and the extra 12 digits presumably are from the 
decimal expansion of the least significant bit?).


But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if 
there's some d function like writeAllDigits or something 
similar.


Thanks in advance for any pointers!

dan


Hi Dan,

What's your usecase here, e.g. a csv/json reader / writer? You 
say it's for double precision numbers (64bit format) then 
provide an example for reals (80bit format). So I'm not certain 
your goal.


If you google "what every developer should know about doubles" 
you'll hit a number of useful articles that explain the common 
issues of floating point representation in detail.


-- David


Thanks David for your reply.

Thanks also berni44 for the information about the dig attribute,
Jon for the neat packaging into one line using the attribute on 
the type.
Unfortunately, the version of gdc that comes with the version of 
debian
that i am using does not have the dig attribute yet, but perhaps 
i can

upgrade, and eventually i think gdc will have it.

And thanks GreatSam4sure for your reply --- i searched the 
archives first,
but very poorly :(.  But it's easy to believe that i'm not the 
first person

in the history of the world with this issue.

Now, my use case is nothing so useful or general as a csv/json 
reader/writer.


I'm just doing some computations, incorrectly i think, and i want 
to be
able to print out the results and feed them to other software.  
I'm trying
to chase down a problem and rule out as many places for error as 
i can, and
it just seemed strange not to be able to get all the digits out 
in some easy way.
But the dig attribute seems to be a big step forward, and for 
that i am grateful.


dan


Re: formatting a float or double in a string with all significant digits kept

2019-10-09 Thread David Briant via Digitalmars-d-learn

On Tuesday, 8 October 2019 at 20:37:03 UTC, dan wrote:
I have a double precision number that i would like to print all 
significant digits of, but no more than what are actually 
present in the number.  Or more exactly, i want to print the 
minimum number of digits necessary to recover the original 
number to within 2 or 3 least significant bits in the stored, 
in-core, version of its bit pattern.


For example,


import std.string;
import std.stdio;
import std.math;

void main( ) {
  auto t = format("%3.30f", PI );
  writeln("Value of PI is: ", PI, " or, : ", t);
}

The default way writeln prints is 5 digits to the right of the 
decimal point.


I can format to print with any number of digits, such as 30 
above, but that's too many.


For pi, the correct number of digits to print looks to be about 
18 (and the extra 12 digits presumably are from the decimal 
expansion of the least significant bit?).


But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if 
there's some d function like writeAllDigits or something 
similar.


Thanks in advance for any pointers!

dan


Hi Dan,

What's your usecase here, e.g. a csv/json reader / writer? You 
say it's for double precision numbers (64bit format) then provide 
an example for reals (80bit format). So I'm not certain your goal.


If you google "what every developer should know about doubles" 
you'll hit a number of useful articles that explain the common 
issues of floating point representation in detail.


-- David


Re: formatting a float or double in a string with all significant digits kept

2019-10-09 Thread GreatSam4sure via Digitalmars-d-learn
On Wednesday, 9 October 2019 at 07:16:43 UTC, Jon Degenhardt 
wrote:

On Wednesday, 9 October 2019 at 05:46:12 UTC, berni44 wrote:

On Tuesday, 8 October 2019 at 20:37:03 UTC, dan wrote:
But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if 
there's some d function like writeAllDigits or something 
similar.


You can use the property .dig to get the number of significant 
digits of a number:


writeln(PI.dig); // => 18

You still need to account for the numbers before the dot. If 
you're happy with scientific notation you can do:


auto t = format("%.*e", PI.dig, PI);
writeln("PI = ",t);


Using the '.dig' property is a really nice idea and looks very 
useful for this. A clarification though - It's the significant 
digits in the data type, not the value. (PI is 18 because it's 
a real, not a double.) So:


writeln(1.0f.dig, ", ", float.dig);  =>  6, 6
writeln(1.0.dig, ", ", double.dig);  => 15, 15
writeln(1.0L.dig, ", ", real.dig);   => 18, 18

Another possibility would be to combine the '.dig' property 
with the "%g" option, similar to the use "%e" shown. For 
example, these lines:


writeln(format("%0.*g", PI.dig, PI));
writeln(format("%0.*g", double.dig, 1.0));
writeln(format("%0.*g", double.dig, 100.0));
writeln(format("%0.*g", double.dig, 1.0001));
writeln(format("%0.*g", double.dig, 0.0001));

produce:

3.14159265358979324
1
100
1.0001
1e-08

Hopefully experimenting with the different formatting options 
available will yield one that works for your use case.




Good solution

But what does it takes to leave a number the way it is without 
formatting automatic to 6 significant figure out how that 
requires such a work around as shown above. I know C language is 
the same but must D follow suit.


One of the compilers, i think the DMD 2.084 (not sure now) 
correct but now the recent one's have revert back. Every number 
should be left the way it is like java, C#(not sure), 
actionscript, javascript, etc.


I don't think it will take that much effort for trivial things 
like to stress developers.


This is the best solution i have ever seen on this issue on the 
forum.i have ask this question several times on this forum




Re: formatting a float or double in a string with all significant digits kept

2019-10-09 Thread Jon Degenhardt via Digitalmars-d-learn

On Wednesday, 9 October 2019 at 05:46:12 UTC, berni44 wrote:

On Tuesday, 8 October 2019 at 20:37:03 UTC, dan wrote:
But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if 
there's some d function like writeAllDigits or something 
similar.


You can use the property .dig to get the number of significant 
digits of a number:


writeln(PI.dig); // => 18

You still need to account for the numbers before the dot. If 
you're happy with scientific notation you can do:


auto t = format("%.*e", PI.dig, PI);
writeln("PI = ",t);


Using the '.dig' property is a really nice idea and looks very 
useful for this. A clarification though - It's the significant 
digits in the data type, not the value. (PI is 18 because it's a 
real, not a double.) So:


writeln(1.0f.dig, ", ", float.dig);  =>  6, 6
writeln(1.0.dig, ", ", double.dig);  => 15, 15
writeln(1.0L.dig, ", ", real.dig);   => 18, 18

Another possibility would be to combine the '.dig' property with 
the "%g" option, similar to the use "%e" shown. For example, 
these lines:


writeln(format("%0.*g", PI.dig, PI));
writeln(format("%0.*g", double.dig, 1.0));
writeln(format("%0.*g", double.dig, 100.0));
writeln(format("%0.*g", double.dig, 1.0001));
writeln(format("%0.*g", double.dig, 0.0001));

produce:

3.14159265358979324
1
100
1.0001
1e-08

Hopefully experimenting with the different formatting options 
available will yield one that works for your use case.


Re: formatting a float or double in a string with all significant digits kept

2019-10-08 Thread berni44 via Digitalmars-d-learn

On Tuesday, 8 October 2019 at 20:37:03 UTC, dan wrote:
But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if 
there's some d function like writeAllDigits or something 
similar.


You can use the property .dig to get the number of significant 
digits of a number:


writeln(PI.dig); // => 18

You still need to account for the numbers before the dot. If 
you're happy with scientific notation you can do:


auto t = format("%.*e", PI.dig, PI);
writeln("PI = ",t);

(By the way, you can shortcut that with writefln!"PI = 
%.*e"(PI.dig, PI);)


If you don't want to use scientific notation, you probably need 
to do some calculations to find out about the number of digits 
before the dot (you need abs to make it work for negative numbers 
too):


import std.conv: to;
auto x = to!int(log10(abs(PI)));
writefln!"%*.*f"(x,PI.dig-x,PI);



formatting a float or double in a string with all significant digits kept

2019-10-08 Thread dan via Digitalmars-d-learn
I have a double precision number that i would like to print all 
significant digits of, but no more than what are actually present 
in the number.  Or more exactly, i want to print the minimum 
number of digits necessary to recover the original number to 
within 2 or 3 least significant bits in the stored, in-core, 
version of its bit pattern.


For example,


import std.string;
import std.stdio;
import std.math;

void main( ) {
  auto t = format("%3.30f", PI );
  writeln("Value of PI is: ", PI, " or, : ", t);
}

The default way writeln prints is 5 digits to the right of the 
decimal point.


I can format to print with any number of digits, such as 30 
above, but that's too many.


For pi, the correct number of digits to print looks to be about 
18 (and the extra 12 digits presumably are from the decimal 
expansion of the least significant bit?).


But i would like to be able to do this without knowing the 
expansion of pi, or writing too much code, especially if there's 
some d function like writeAllDigits or something similar.


Thanks in advance for any pointers!

dan