简体   繁体   中英

Failure of the Round-trip format specifier “R” in .Net

The documentation recommends that I use G17 rather than R , as R can sometimes fail to round-trip.

However, (1.0/10).ToString("G17") gives "0.10000000000000001" , which is pretty horrible. while the round-trip format seems to work just fine (and gives "0.1" ). I'm happy to spend a few cpu cycles in order to get a more aesthetic result. But potential round-trip failures are more concerning.

For what sort of (Double) values does R fail to round-trip? And how badly? Does the .Net version (we run on both Net Framework 4.72 and NetCore 3.1) affect things? Could writing on one platform and reading on another make round-trip failure more frequent?

We are considering writing doubles to R first, parsing to check the round-trip, and falling back to G17 only if that fails. Is there a better way to get nicely formatted, reliable results?

Round trip here is a numeric value that is converted to a string is parsed back into the same numeric value .

OP's dismay with (1.0/10).ToString("G17") gives "0.10000000000000001", which is pretty horrible. is an incorrect assessment of round trip success. The intermediate string is only half of the round trip .

Double exactly encodes about 2 64 different values. All encodable values are some limited integer * 2 some_power . 0.1 is not one of them. 1.0/10 makes a math quotient of 0.1, but a slightly different Double value. The closest Double value and it two closet Double neighbors:

 Before     0.099999999999999991673... 
            0.100000000000000005551...
 After      0.100000000000000019428...
 OP report  0.10000000000000001
 Digit count  12345678901234567

OP's example should then be <(0.100000000000000005551).ToString("G17") gives "0.10000000000000001"> which is good .

Printing a Double with G17 provides 17 significant digits, enough to successfully round trip.


For what sort of (Double) values does R fail to round-trip? And how badly?

For this, I go on memory. R sometimes used less than 17 significant digits, like 15, to form the intermediate string. The algorithm used to determine the digit count sometimes came up a bit short and hence "some cases fails to successfully round-trip the original value".

Using G17 always works. For some values, less than 17 also would have worked. The down-side to G17 is exactly in cases like this. Fewer than 17 digits would have worked and have provided a more pleasing, shorter intermediate string.

A pleasing human readable string is not the goal of round-tripping. The goal is to form the same Double after going form value to string to value, even if the intermediate string has extra digits in select cases.


Is there a better way to get nicely formatted, reliable results?

"nicely formatted" is an additional burden to round trip . MS attempted to do so with R and failed in some cases, preferring to retain the same broken functionality than to fix it.

OP would be wise to avoid that path and forego the goal of nicely formatted intermediate string and focus on the round-trip goal of getting the final same value back.

Use G17 .


We are considering writing doubles to R first, parsing to check the round-trip, and falling back to G17 only if that fails.

That would work if done correctly. To assess correctness, test your code with many values and also post it and the test harness for code review.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM