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?

+3


source to share


1 answer


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 ...

0


source







All Articles