0

I know that binary storage for floats cannot always store the exact value. I know that .NET Framework only displays up to 7 significant digits for floats, and uses the 8th to round the 7th. I also know that the full value is used in calculations.

example code:

var f1 = 461168601842738790f; // 461,168,608,714,686,464 (closest float)
var f2 = f1 * 3f;             // 1,383,505,826,144,059,392
                              // 1,383,505,860,503,797,760 (closest float)
var l1 = (long)f1;
var l2 = (long)f2;
Console.WriteLine($"f1: {f1:#,###}\nl1: {l1:#,###}\n\nf2: {f2:#,###}\nl2: {l2:#,###}");

/* displays:
f1: 461,168,600,000,000,000
l1: 461,168,608,714,686,464

f2: 1,383,506,000,000,000,000
l2: 1,383,505,860,503,797,760
 */

We can see that the full value is used in math and conversions. So how can we force .NET Framework (c# in particular) to display the full float value as a string?

Casting to long isn't a good option as the value could be larger than a long or be a decimal value. I've tried various string formatting options, but can't seem to find a way to display the full float value.

30
  • 2
    The Standard Formats display them, such as N0 see learn.microsoft.com/en-us/dotnet/standard/base-types/… and dotnetfiddle.net/BIOtdU Commented May 12 at 0:16
  • 2
    The question of what to print is about the information content. And for that a float only contains 23 bits which is about 7 decimal digits. Displaying significantly more creates an illusion of information that is not there. Thus the default formatting produces a string that contains 7 rounded decimals, as that is enough, there is no more inside that number. One could argue about using 8 decimals, or for absolutely safe safety 9. Commented May 12 at 5:07
  • 2
    @LutzLehmann there are situations where you might want to write floating point numbers (hard won optimised polynomial coefficients for instance) in human readable form that can be read in again and convert back exactly to the original IEEE 754 FP number that you started with. Unless you have at least a few guard digits in decimal notation you will lose the LSB of the mantissa on the round trip. C/C++ formatting provides the hexadecimal output format "a" of the form [-]h.hhhhp[+|-]dd which exactly specifies an IEEE 754 single precision number in ASCII text form. Is there no equivalent in C#? Commented May 12 at 8:20
  • 2
    Yeah, as in a previous comment, we found that starting with .net core 3.0, they changed it so using "n" does what I want. Unfortunately, I'm stuck using framework 4.7.2 in which "n" does not show all the digits. Commented May 12 at 8:49
  • 2
    @LutzLehmann: Re “The question of what to print is about the information content”: No, it is not. Different people print numbers for different reasons at different times. Sometimes the purpose is just to convey to a casual reader the value of an approximately computed value. Sometimes the purpose is to display the value sufficiently well to transport it (across storage or communication) to input elsewhere and reproduce the value. Sometimes the purpose is to display the exact represented value for debugging purposes. Here, OP has asked to display the actual value, and so that is the question. Commented May 12 at 18:28

1 Answer 1

3

You seem to be targeting the legacy .NET Framework which does not have full support for formatting (or parsing) of floating-point numbers.

In .NET (since .NET Core 3.0 from 2019), you can use format string G99 or even G999 to show many (99 or 999, respectively) significant digits.

Try with .NET Fiddle

Console.WriteLine($"f1: {f1:G999}\nl1: {l1}\n\nf2: {f2:G999}\nl2: {l2}");

(Here is what happens if you attempt the same with .NET Framework: Fiddle with target .NET Framework - You see that only 9 (for float or System.Single) respectively 17 (for double) figures can be provided, no matter what formatting string you attempt, in .NET Framework.)

So your best option is to upgrade to .NET. If that is not possible (you have to stay on .NET Framework), then find a third-party package that supports this.

Here is a blog post about the 2019 changes that made floating-point formatting and parsing compliant with IEEE: Floating-Point Parsing and Formatting improvements in .NET Core 3.0

Sign up to request clarification or add additional context in comments.

2 Comments

Yes, we found this out in the comments above. I even found the same blog post you linked. I realize there aren't any string formatting options that does what I want - hence me asking the question. I was hoping there might be a format option I wasn't aware of, or some trick to force it, or some other relatively easy method to do what I want. Other than parsing the bits and doing the math manually, that is. It seems like such an obvious thing to want to do. Thanks anyway.
@JeffShepler Looks like f1090 works fine with -DBL_TRUE_MIN via .NET Fiddle.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.