I would like to save float numbers in a binary file and read them afterwards for further processing. Unfortunately, fwrite and afterwards fread does change the number.
Following simple example:
% Number to store
A = 0.123456789101112
% Generate and open txt file
fid = fopen('test_fread.txt','w','b');
% write A into test_fread.txt
fwrite(fid,A,'float32');
% close file
fclose(fid)
% open txt file
fid = fopen('test_fread.txt','r','b');
% read the file
fread(fid,'float32')
ans = 0.123456791043282
The answer is different than the input. How can I fix this? What should I search for? Is it rounding, precision or another problem?
Floating point numbers are never exact. single
precision floats (float32
) only have 6-9 decimals of precision. For the pure decimal case this translates to the issue that you're seeing. The effect is more exaggerated if you also have an integer component:
% Sample number
A = 123456789.123456789;
% Write, rewind, and read back in
fID = fopen('test_fread.txt', 'w+', 'b');
fwrite(fID, A, 'float32');
frewind(fID);
B = fread(fID,'float32');
fclose(fID);
fprintf('A: %15.15f\nB: %15.15f\n', A, B);
Which returns:
A: 123456789.123456790000000
B: 123456792.000000000000000
Note that MATLAB casts B
as a double
here.
MATLAB's default data type, double
(float64
) has double the bits available, which will give you 15-17 significant decimal digits. Using the previous example we can try:
% Sample number
A = 123456789.123456789;
% Write, rewind, and read back in
fID = fopen('test_fread.txt', 'w+', 'b');
fwrite(fID, A, 'float64');
frewind(fID);
B = fread(fID,'float64');
fclose(fID);
fprintf('A: %15.15f\nB: %15.15f\n', A, B);
Which returns:
A: 123456789.123456790000000
B: 123456789.123456790000000
Yay.
If you need better precision in MATLAB than double
you will need to look into using vpa
, which is part of the Symbolic Math Toolbox, or a similar package that offers higher/variable precision.