My script reads a string value "0.001044397222448" from a file, and after parisng the file this value ends up as double precission: > format long > value_double value_double = 0.001044397222448 After I convert this number to singe using value_float = single(value_double), the value is: > value_float value_float = 0.0010444 What is the real value of this variable, that I later use in my Simulink simulation? Is it really truncated/rounded to 0.0010444? My problem is that later on, after I compare this with analogous C code, I get differences. In the C code the value is read as float gf = 0.001044397222448f; and it prints out as `0.001044397242367267608642578125000`. So the C code keeps good precission. But, does Matlab?
Prashant Kumar answered .
2025-11-20
Next Rep. Value Above 0.001044397358782589435577392578125 Quantized Value 0.001044397242367267608642578125 Next Rep. Value Below 0.001044397125951945781707763671875
Let's also show the ideal mid-points between these three values. (Note, the midpoints are NOT representable in the type.)
Next Rep. Value Above 0.001044397358782589435577392578125 Mid-point Value Above 0.0010443973005749285221099853515625 Quantized Value 0.001044397242367267608642578125 Mid-point Value Below 0.0010443971841596066951751708984375 Next Rep. Value Below 0.001044397125951945781707763671875
Given these values, we can say if the decimal text's value, as interpreted in the world of ideal math, is within this range
0.0010443973005749285221099853515625 > decimalText > 0.0010443971841596066951751708984375
then MATLAB, a C compiler, etc., parsing that text would round it to this representable value of type single
0.001044397242367267608642578125
Sufficient digits and superflous digits
Let's look at our mid-point values again
Mid-point Value Above 0.0010443973005749285221099853515625 Mid-point Value Below 0.0010443971841596066951751708984375
and think about when fewer digits are sufficient to be certain we are between these two values.
Consider this example,
Mid-point Value Above 0.0010443973005749285221099853515625
0.0010443972xxx...
Mid-point Value Below 0.0010443971841596066951751708984375
format hex nDigitsOfPrecision = 8; vOrig = single(0.001044397242367267608642578125); vOrig = vOrig+eps(vOrig)*[1,0,-1] vTextDig7 = mat2str(vOrig,'class',nDigitsOfPrecision-1) vRoundTripDig7 = eval(vTextDig7) format long worstCaseErrorDig7 = max(abs(vRoundTripDig7 - vOrig)) format hex vTextDig8 = mat2str(vOrig,'class',nDigitsOfPrecision) vRoundTripDig8 = eval(vTextDig8) format long worstCaseErrorDig8 = max(abs(vRoundTripDig8 - vOrig))
The output shows 7 digits was not lossless, but 8 digits was.
vOrig =
1×3 single row vector
3a88e429 3a88e428 3a88e427
vTextDig7 =
'single([0.001044397 0.001044397 0.001044397])'
vRoundTripDig7 =
1×3 single row vector
3a88e426 3a88e426 3a88e426
worstCaseErrorDig7 =
single
3.4924597e-10
vTextDig8 =
'single([0.0010443974 0.0010443972 0.0010443971])'
vRoundTripDig8 =
1×3 single row vector
3a88e429 3a88e428 3a88e427
worstCaseErrorDig8 =
single
0
Note 8 digits for single is sufficient to be lossless, but for individual values 8 digits may not be necessary. For example, for the individual value single(0.01), one digit is sufficient for lossless roundtrip.
nDigitsOfPrecision = 1 vOrig = single(0.01) format hex vOrig vTextDig1 = mat2str(vOrig,'class',nDigitsOfPrecision) vRoundTripDig1 = eval(vTextDig1) format long vRoundTripDig1 worstCaseErrorDig1 = max(abs(vRoundTripDig1 - vOrig))
which outputs
nDigitsOfPrecision =
1
vOrig =
single
0.0100000
vOrig =
single
3c23d70a
vTextDig1 =
'single(0.01)'
vRoundTripDig1 =
single
3c23d70a
vRoundTripDig1 =
single
0.0100000
worstCaseErrorDig1 =
single
0