1

I'm trying to import float data from a text file. In order to do so, I load the individual lines from the file to a string and than parse it with sscanf (textscan shows similar behavior). For some reason, sscanf adds some deviations in the last few decimal places as can be seen when outputting variables as long

'8.2' --> 8.199999999999999.

In addition, after converting 8.2 GHz to 8.2e9 Hz (Imported_array=Imported_array*10^9), the call

Bin=find(Imported_array==Lookup_Value);

returns an empty matrix.

A minimal example looks as follows:

clc;
clear;

format long;

% String to Parse from Textfile(f in GHz)
string='8.200000000 1.406320e-01 -8.175100e-02 -6.981310e-04 1.972470e-03 -1.049100e-03 1.868090e-03 1.620270e-01 -8.879710e-02';

% Same Problem with a single number
% string='8.2';

% Lookup Value (in Hz)
fstart=8.2e9;

% Parse String
f=sscanf(string, '%f')

% Convert GHz to Hz
f=f*10^9

% Search Bin
Bin=find(f==fstart)
  • When using string='8.2', the same problem occurs.
  • For string=8 and fstart=8e9 everything works fine.
  • textscan shows similar behavior.

Where do I go wrong in the above example?

The problem occurs in R2015a,b and R2014a as well, both on MAC OS and Win machines.

Any hints are highly appreciated!

Regards

1 Answers1

0

You should never compare two floats for equality without incorporating a tolerance. See: What Every Computer Scientist Should Know About Floating-Point Arithmetic and Accuracy of Floating Point Data.

One potential method:

% String to Parse from Textfile(f in GHz)
string='8.200000000 1.406320e-01 -8.175100e-02 -6.981310e-04 1.972470e-03 -1.049100e-03 1.868090e-03 1.620270e-01 -8.879710e-02';

% Lookup Value (in Hz)
fstart=8.2e9;

% Parse String
f=sscanf(string, '%f')

% Convert GHz to Hz
f=f*10^9

% Search Bin within tolerance
diffs = abs(f - fstart);
tol = 10^-6;
Bin=find(diffs < tol)

Which returns:

Bin =

     1

It's worth noting here that when you multiply f by 10^9 you're also multiplying the error, which is the reason for such a (relatively) large tolerance. In cases where you're not manipulating the number before testing for equality you generally can check for equality by seeing if the absolute difference is less than eps, which is the machine's floating-point relative accuracy.

sco1
  • 12,154
  • 5
  • 26
  • 48