Thread Subject: Find and precision

Subject: Find and precision

From: Luca Zanotti Fragonara

Date: 30 Sep, 2008 10:32:01

Message: 1 of 9

I need to use the find function on an array that I've created from a textscan of .txt file. The problem is that I've some data that in my array are in the form:

2.142199999999999 instead of 2.1422.

It's very weird, because in my txt file the data are in the form 2.1422.

So my problem is that, when I use the find function I need to find the row in which is stored the 2.1422, but it didn't match it because the number slightly different. Or at least, I guess so.

Do you have any suggestions?

Subject: Find and precision

From: nor ki

Date: 30 Sep, 2008 10:55:04

Message: 2 of 9

"Luca Zanotti Fragonara" <Luca_Zanotti@libero.it> wrote in message <gbsv71$7mq$1@fred.mathworks.com>...
> I need to use the find function on an array that I've created from a textscan of .txt file. The problem is that I've some data that in my array are in the form:
>
> 2.142199999999999 instead of 2.1422.
>
> It's very weird, because in my txt file the data are in the form 2.1422.
>
> So my problem is that, when I use the find function I need to find the row in which is stored the 2.1422, but it didn't match it because the number slightly different. Or at least, I guess so.
>
> Do you have any suggestions?


one simple workaround would be to round the numbers to your desired precision

numdigit = 4
multiplicator = 10^4

data = round(data*multiplicator)/multiplicator

this is not elegant but works, of course reading the correct content would be better

Subject: Find and precision

From: Luca Zanotti Fragonara

Date: 30 Sep, 2008 11:11:02

Message: 3 of 9

Thanks, I think too that this is the only easy way.

Subject: Find and precision

From: Steve Amphlett

Date: 30 Sep, 2008 12:18:02

Message: 4 of 9

"Luca Zanotti Fragonara" <Luca_Zanotti@libero.it> wrote in message <gbt1g5$pea$1@fred.mathworks.com>...
> Thanks, I think too that this is the only easy way.
>

Attempts to round numbers like this won't work. Double precision is unable to store a number like 2.1422 exactly (or most decimals for that matter). So you must bear this in mind when comparing values (do not use ==).

There have been a few posts recently questioning the find function. find simply returns the indices of non-zero elements. Its function does not depend on precision in any way. If you pass the result of a bad comparison to find, it'll probably not return what you'd hoped.

Subject: Find and precision

From: Carlos Adrian Vargas Aguilera

Date: 30 Sep, 2008 12:49:01

Message: 5 of 9

I've make a function, NUMCMP, that works with this problem, but I'm not sure if it is the correct way. The user must specify the precision then the decimal point moves to it, rounds and compares.
Although, before I rest all of the inputs by the minimun data, so the moving decimal won't lead to a huge values (for example, when comparing serial dates up to seconds):

>> numcmp(X,'>=',Y,1) % does: (X>=Y) up to 0.1
>> numcmp(X,'>=',Y,5) % does: (X>=Y) up to 0.00001

so use

>> if numcmp(X,'==',2.1422,5), ...

instead of

>> if (X==2.1422), ...

http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=21190



Carlos Vargas

Subject: Find and precision

From: Jos

Date: 30 Sep, 2008 13:39:02

Message: 6 of 9

"Carlos Adrian Vargas Aguilera" <nubeobscura@hotmail.com> wrote in message <gbt77t$q6e$1@fred.mathworks.com>...
> I've make a function, NUMCMP, that works with this problem, but I'm not sure if it is the correct way. The user must specify the precision then the decimal point moves to it, rounds and compares.
> Although, before I rest all of the inputs by the minimun data, so the moving decimal won't lead to a huge values (for example, when comparing serial dates up to seconds):
>
> >> numcmp(X,'>=',Y,1) % does: (X>=Y) up to 0.1
> >> numcmp(X,'>=',Y,5) % does: (X>=Y) up to 0.00001
>
> so use
>
> >> if numcmp(X,'==',2.1422,5), ...
>
> instead of
>
> >> if (X==2.1422), ...
>
> http://www.mathworks.com/matlabcentral/fileexchange/loadFile.do?objectId=21190
>
>
>
> Carlos Vargas

or just simply

round(10.^5 * X) == round(10.^5 * Y)

Jos

Subject: Find and precision

From: Walter Roberson

Date: 30 Sep, 2008 14:37:15

Message: 7 of 9

nor ki wrote:
> "Luca Zanotti Fragonara" <Luca_Zanotti@libero.it> wrote in message <gbsv71$7mq$1@fred.mathworks.com>...
>> I need to use the find function on an array that I've created from a textscan
>> of .txt file. The problem is that I've some data that in my array are in the form:
>> 2.142199999999999 instead of 2.1422.
>> It's very weird, because in my txt file the data are in the form 2.1422.
>> So my problem is that, when I use the find function I need to find the row in
>> which is stored the 2.1422, but it didn't match it because the number slightly
>> different. Or at least, I guess so.

> one simple workaround would be to round the numbers to your desired precision

> numdigit = 4
> multiplicator = 10^4
> data = round(data*multiplicator)/multiplicator

No, that doesn't work. Try it yourself:

>> r = rand; sprintf('%.55g\n%.55g', r, round(r*10^4)/10^4)

ans =

0.81472368639317893634910205946653150022029876708984375
0.8146999999999999797495320308371447026729583740234375

If that rounding worked, the second value would be 0.8147 -exactly-.
However, the rounding CANNOT work in any binary floating point number
system, because 1/10 (and hence 1/100, 1/1000 etc) does not have
an exact representation in any finite binary system, just the same
way that you cannot -exactly- represent 1/3 in any finite number
of decimal digits.


You should almost never test for floating point equality. You
should instead test for the value being "close enough". Not

RowsWithMatch = find(any(TheMatrix == 2.1422,2));

but rather something like

RowsWithMatch = find(any(abs(TheMatrix - 2.1422) < 0.0001,2));

where 0.0001 is the (problem-specific) tolerance within which you want
a match to be deemed to have occurred. (The 2 as the second argument of
any() tells any() to look along the rows instead of down the columns.)

This difficulty with inexact representation of numbers applies in *any*
number representation system that uses a finite number of digits -- it
even applies in number representation systems that use variable number bases.
No finite number representation system can -exactly- represent pi
or any other transcendental number.

Subject: Find and precision

From: Matt Fig

Date: 30 Sep, 2008 17:07:20

Message: 8 of 9

Walter Roberson <roberson@hushmail.com> wrote in message
>
> No, that doesn't work. Try it yourself:
>
> >> r = rand; sprintf('%.55g\n%.55g', r, round(r*10^4)/10^4)
>
> ans =
>
> 0.81472368639317893634910205946653150022029876708984375
> 0.8146999999999999797495320308371447026729583740234375
>

Understood, and I'm not denying the above results, but(!):

rand('twister',5489) % Get the same number W.R. as above.
r = rand;
.8147 == round(r*10^4)/10^4
ans =

     1

 
> You should almost never test for floating point equality. > You
> should instead test for the value being "close enough".


Agreed!
I am only curious why we get that result that the numbers are equal? Before I became "wiser" to the idea of testing for close enough, I used the "up-down" method of round-then-compare with these types of problems for years. I never found it to fail, probably by luck I admit. Can anyone demonstrate it to fail by following what I did above? For example, calling the next random number:

r = rand;
round(r*10^10)/10^10 == 0.9057919371
ans =

     1


Just curious.

Subject: Find and precision

From: nor ki

Date: 1 Oct, 2008 08:45:03

Message: 9 of 9

Walter Roberson <roberson@hushmail.com> wrote in message <8QqEk.5075$YN5.2821@newsfe03.iad>...
> nor ki wrote:
> > "Luca Zanotti Fragonara" <Luca_Zanotti@libero.it> wrote in message <gbsv71$7mq$1@fred.mathworks.com>...
> >> I need to use the find function on an array that I've created from a textscan
> >> of .txt file. The problem is that I've some data that in my array are in the form:
> >> 2.142199999999999 instead of 2.1422.
> >> It's very weird, because in my txt file the data are in the form 2.1422.
> >> So my problem is that, when I use the find function I need to find the row in
> >> which is stored the 2.1422, but it didn't match it because the number slightly
> >> different. Or at least, I guess so.
>
> > one simple workaround would be to round the numbers to your desired precision
>
> > numdigit = 4
> > multiplicator = 10^4
> > data = round(data*multiplicator)/multiplicator
>
> No, that doesn't work. Try it yourself:
>
> >> r = rand; sprintf('%.55g\n%.55g', r, round(r*10^4)/10^4)
>
> ans =
>
> 0.81472368639317893634910205946653150022029876708984375
> 0.8146999999999999797495320308371447026729583740234375
>
> If that rounding worked, the second value would be 0.8147 -exactly-.
> However, the rounding CANNOT work in any binary floating point number
> system, because 1/10 (and hence 1/100, 1/1000 etc) does not have
> an exact representation in any finite binary system, just the same
> way that you cannot -exactly- represent 1/3 in any finite number
> of decimal digits.
>
>
> You should almost never test for floating point equality. You
> should instead test for the value being "close enough". Not
>
> RowsWithMatch = find(any(TheMatrix == 2.1422,2));
>
> but rather something like
>
> RowsWithMatch = find(any(abs(TheMatrix - 2.1422) < 0.0001,2));
>
> where 0.0001 is the (problem-specific) tolerance within which you want
> a match to be deemed to have occurred. (The 2 as the second argument of
> any() tells any() to look along the rows instead of down the columns.)
>
> This difficulty with inexact representation of numbers applies in *any*
> number representation system that uses a finite number of digits -- it
> even applies in number representation systems that use variable number bases.
> No finite number representation system can -exactly- represent pi
> or any other transcendental number.

Hello Walter,

thanks for that one

Best
kinor

Tags for this Thread

Everyone's Tags:

Add a New Tag:

Separated by commas
Ex.: root locus, bode

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Tag Activity for This Thread
Tag Applied By Date/Time
numcmp Carlos Adrian Vargas Aguilera 30 Sep, 2008 08:50:06
find precision Luca Zanotti Fragonara 30 Sep, 2008 06:35:05
rssFeed for this Thread

Public Submission Policy

NOTICE: Any content you submit to MATLAB Central, including personal information, is not subject to the protections which may be afforded information collected under other sections of The MathWorks, Inc. Web site. You are entirely responsible for all content that you upload, post, e-mail, transmit or otherwise make available via MATLAB Central. The MathWorks does not control the content posted by visitors to MATLAB Central and, does not guarantee the accuracy, integrity, or quality of such content. Under no circumstances will The MathWorks be liable in any way for any content not authored by The MathWorks, or any loss or damage of any kind incurred as a result of the use of any content posted, e-mailed, transmitted or otherwise made available via MATLAB Central. Read the complete Disclaimer prior to use.

Contact us at files@mathworks.com