Is it safe to make the result of Math.Round float?
A colleague wrote the code in the following lines:
var roundedNumber = (float) Math.Round(someFloat, 2);
Console.WriteLine(roundedNumber);
I have an ambiguity about this code - is the number written here even guaranteed that you already have 2 decimal places? It seems plausible to me that truncating a double Math.Round(someFloat, 2)
to float
might result in a number whose string representation has more than two digits. Can anyone provide an example of this (demonstrating that such a cast is unsafe) or somehow demonstrate that it is safe to do such a cast?
source to share
Assuming IEEE754 single and double precision representation and rules, I checked the first 2 ^ 24 integers i
which
float(double( i/100 )) = float(i/100)
In other words, converting a decimal value with two decimal places twice (from the first to the nearest double, and then to the nearest single precision float) is the same as converting a decimal number directly to single precision, as long as the integer part of the decimal value is not too large.
I have no guarantee of large values.
The double approximation and the single approximation are different, but this is not really a question.
Converting twice is harmless, at least before 167772.16
, it is the same as Math.Round would do it right in single precision.
Here is the testing code in Squeak / Pharo Smalltalk with the ArbitraryPrecisionFloat package (sorry not showing it in C #, but the language doesn't really matter, just IEEE rules).
(1 to: 1<<24)
detect: [:i |
(i/100.0 asArbitraryPrecisionFloatNumBits: 24) ~= (i/100 asArbitraryPrecisionFloatNumBits: 24) ]
ifNone: [nil].
EDIT
The above test was overkill because, thanks to the excellent recommendation provided by Mark Dickinson ( Useless Double Rounding of Basic Arithmetic Operations ), we know that Execution float(double(x) / double(y))
results in the correct rounded value for x / y
if x
and are y
represented as floats, which is the case for any 0 <= x <= 2^24
and for y=100
.
EDIT
I checked with numerators up to 2 ^ 30 (decimal> 10 million) and converting twice is still identical to converting once. Continuing with interpreted language is not good due to global warming ...
source to share