Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Strange rounding behaviour error?

Subject: Strange rounding behaviour error?

From: Richard Crozier

Date: 26 Oct, 2009 11:03:02

Message: 1 of 6

Hello,

I've noticed some undesireable behaviour in some code I've written, which may or may not be an error, but for which I would like some advice on how to work around.

I have some code which partitions a region of space into 49 sections. On the lines running between these sections I am able to determine the exact value of a function I am interested in. Then to estimate the value of the function between these lines, I then interpolate between the values on these lines either side of a point I am interested in. To do this I first have to find the correct lines either side of the point I wish to evaluate which is where I'm getting an odd error.

By chance one of the points I wish to evaluate has come out as a value very close to one of the lines. The nearest line is at the line x=0.4, and my actual point has the x position 0.4 - 5.5511e-017. This is just under 0.4, which I discovered with the following code:

xyCoords(19,2) - 0.4

ans =

 -5.5511e-017

The region is split into 50 lines, and the correct lines either side of this point are the lines at x=0.38 and x = 0.4. However, if I do the following to find the nearest line below this point:

>> floor(rzCoords(19,2) * 50)/50

ans =

    0.4000

I get the answer above which is not the line below the point as desired. For comparison, if I do:

>> floor(0.399999999*50)/50

ans =

    0.3800

I get the correct line, the line at 0.38. To check what's going on I can also do the following to confirm that the number is definately less than 0.4:

>> xyCoords(19,2) == 0.4

ans =

     0

>> xyCoords(19,2) < 0.4

ans =

     1

This is a major problem, because if I then use the interp1 function as I would like to, as below for instance:

interp1([0.4, 0.42], [0.12154, 0.154894], abs(xyCoords(19,2)))

I get the result NaN as it lies outside the range of the data.

The problem appears to be that xyCoords(19,2) * 50 yields exactly 20, as shown below:

>> rzCoords(19,2) * 50

ans =

    20

>> ans == 20

ans =

     1

not a value just under 20 as it should be. What is the best way to fix this?

Subject: Strange rounding behaviour error?

From: Steven Lord

Date: 26 Oct, 2009 13:38:20

Message: 2 of 6


"Richard Crozier" <r.crozier@ed.ac.uk> wrote in message
news:hc3vl6$oag$1@fred.mathworks.com...
> Hello,
>
> I've noticed some undesireable behaviour in some code I've written, which
> may or may not be an error, but for which I would like some advice on how
> to work around.
>
> I have some code which partitions a region of space into 49 sections. On
> the lines running between these sections I am able to determine the exact
> value of a function I am interested in. Then to estimate the value of the
> function between these lines, I then interpolate between the values on
> these lines either side of a point I am interested in. To do this I first
> have to find the correct lines either side of the point I wish to evaluate
> which is where I'm getting an odd error.
>
> By chance one of the points I wish to evaluate has come out as a value
> very close to one of the lines. The nearest line is at the line x=0.4, and
> my actual point has the x position 0.4 - 5.5511e-017. This is just under
> 0.4, which I discovered with the following code:
>
> xyCoords(19,2) - 0.4
>
> ans =
>
> -5.5511e-017

This is approximately eps(0.4) -- about the "spacing" between adjacent
floating point numbers in the vicinity of 0.4.

Read this document for more information about floating point numbers and
EPS:

http://www.mathworks.com/company/newsletters/news_notes/pdf/Fall96Cleve.pdf

> The region is split into 50 lines, and the correct lines either side of
> this point are the lines at x=0.38 and x = 0.4. However, if I do the
> following to find the nearest line below this point:
>
>>> floor(rzCoords(19,2) * 50)/50
> ans =
>
> 0.4000
>
> I get the answer above which is not the line below the point as desired.
> For comparison, if I do:

However, it is the correct answer.

Look at:

format hex
rzCoords(19, 2)
0.4
rzCoords(19, 2)*50
20

The difference between rzCoords(19, 2) and 0.4 is so small that when you
multiply the expression by 50, the difference between 50*rzCoords(19, 2) and
20 is too insignificant (in the floating-point arithmetic sense) to be
represented in the result of the calculation.

>>> floor(0.399999999*50)/50
>
> ans =
>
> 0.3800
>
> I get the correct line, the line at 0.38. To check what's going on I can
> also do the following to confirm that the number is definately less than
> 0.4:
>
>>> xyCoords(19,2) == 0.4
>
> ans =
>
> 0
>
>>> xyCoords(19,2) < 0.4
>
> ans =
>
> 1

Suppose I give you a bank account containing $1,000. Not bad, huh? Now I
add $0.001 to your bank account. You don't really care about that, do you?
Now what if I multiplied the contents of your bank account by 1000? Would
you say that you had $1,000,000 or that you had $1,000,001?

> This is a major problem, because if I then use the interp1 function as I
> would like to, as below for instance:
>
> interp1([0.4, 0.42], [0.12154, 0.154894], abs(xyCoords(19,2)))
>
> I get the result NaN as it lies outside the range of the data.
>
> The problem appears to be that xyCoords(19,2) * 50 yields exactly 20, as
> shown below:
>
>>> rzCoords(19,2) * 50
>
> ans =
>
> 20
>
>>> ans == 20
>
> ans =
>
> 1
>
> not a value just under 20 as it should be. What is the best way to fix
> this?

Make your calculations robust to floating-point arithmetic.

--
Steve Lord
slord@mathworks.com
comp.soft-sys.matlab (CSSM) FAQ: http://matlabwiki.mathworks.com/MATLAB_FAQ

Subject: Strange rounding behaviour error?

From: someone

Date: 26 Oct, 2009 13:45:23

Message: 3 of 6

"Richard Crozier" <r.crozier@ed.ac.uk> wrote in message <hc3vl6$oag$1@fred.mathworks.com>...
> Hello,
>
> I've noticed some undesireable behaviour in some code I've written, which may or may not be an error, but for which I would like some advice on how to work around.
>
> I have some code which partitions a region of space into 49 sections. On the lines running between these sections I am able to determine the exact value of a function I am interested in. Then to estimate the value of the function between these lines, I then interpolate between the values on these lines either side of a point I am interested in. To do this I first have to find the correct lines either side of the point I wish to evaluate which is where I'm getting an odd error.
>
> By chance one of the points I wish to evaluate has come out as a value very close to one of the lines. The nearest line is at the line x=0.4, and my actual point has the x position 0.4 - 5.5511e-017. This is just under 0.4, which I discovered with the following code:
>
> xyCoords(19,2) - 0.4
>
> ans =
>
> -5.5511e-017
>
> The region is split into 50 lines, and the correct lines either side of this point are the lines at x=0.38 and x = 0.4. However, if I do the following to find the nearest line below this point:
>
> >> floor(rzCoords(19,2) * 50)/50
>
> ans =
>
> 0.4000
>
> I get the answer above which is not the line below the point as desired. For comparison, if I do:
>
> >> floor(0.399999999*50)/50
>
> ans =
>
> 0.3800
>
> I get the correct line, the line at 0.38. To check what's going on I can also do the following to confirm that the number is definately less than 0.4:
>
> >> xyCoords(19,2) == 0.4
>
> ans =
>
> 0
>
> >> xyCoords(19,2) < 0.4
>
> ans =
>
> 1
>
> This is a major problem, because if I then use the interp1 function as I would like to, as below for instance:
>
> interp1([0.4, 0.42], [0.12154, 0.154894], abs(xyCoords(19,2)))
>
> I get the result NaN as it lies outside the range of the data.
>
> The problem appears to be that xyCoords(19,2) * 50 yields exactly 20, as shown below:
>
> >> rzCoords(19,2) * 50
>
> ans =
>
> 20
>
> >> ans == 20
>
> ans =
>
> 1
>
> not a value just under 20 as it should be. What is the best way to fix this?

Welcome to the world of floating point math!
There are many anomalies that can occur such as:

a + (b + c) ~= (a + b) + c

For a detailed explanation see the answer to Q6.1 of the MATLAB FAQ at:
http://matlabwiki.mathworks.com/MATLAB_FAQ

A "quick fix" to your above problem might be
to use the 'extrap' option with interp1. That
will get rid of the NaNs at least, but it might
not necessarily give you the "correct" answer.

Making code that is robust in these kinds of
situations is what keep programmers employed.

Subject: Strange rounding behaviour error?

From: the cyclist

Date: 26 Oct, 2009 14:00:23

Message: 4 of 6

"Richard Crozier" <r.crozier@ed.ac.uk> wrote in message <hc3vl6$oag$1@fred.mathworks.com>...
> Hello,
>
> I've noticed some undesireable behaviour in some code I've written, which may or may not be an error, but for which I would like some advice on how to work around.
>
> I have some code which partitions a region of space into 49 sections. On the lines running between these sections I am able to determine the exact value of a function I am interested in. Then to estimate the value of the function between these lines, I then interpolate between the values on these lines either side of a point I am interested in. To do this I first have to find the correct lines either side of the point I wish to evaluate which is where I'm getting an odd error.
>
> By chance one of the points I wish to evaluate has come out as a value very close to one of the lines. The nearest line is at the line x=0.4, and my actual point has the x position 0.4 - 5.5511e-017. This is just under 0.4, which I discovered with the following code:
>
> xyCoords(19,2) - 0.4
>
> ans =
>
> -5.5511e-017
>
> The region is split into 50 lines, and the correct lines either side of this point are the lines at x=0.38 and x = 0.4. However, if I do the following to find the nearest line below this point:
>
> >> floor(rzCoords(19,2) * 50)/50
>
> ans =
>
> 0.4000
>
> I get the answer above which is not the line below the point as desired. For comparison, if I do:
>
> >> floor(0.399999999*50)/50
>
> ans =
>
> 0.3800
>
> I get the correct line, the line at 0.38. To check what's going on I can also do the following to confirm that the number is definately less than 0.4:
>
> >> xyCoords(19,2) == 0.4
>
> ans =
>
> 0
>
> >> xyCoords(19,2) < 0.4
>
> ans =
>
> 1
>
> This is a major problem, because if I then use the interp1 function as I would like to, as below for instance:
>
> interp1([0.4, 0.42], [0.12154, 0.154894], abs(xyCoords(19,2)))
>
> I get the result NaN as it lies outside the range of the data.
>
> The problem appears to be that xyCoords(19,2) * 50 yields exactly 20, as shown below:
>
> >> rzCoords(19,2) * 50
>
> ans =
>
> 20
>
> >> ans == 20
>
> ans =
>
> 1
>
> not a value just under 20 as it should be. What is the best way to fix this?

I can't say I have the best way to fix this problem, which as you have basically figured out is related to how floating point numbers are calculated.

I have one thought on this. It seems that your difficulty is primarily due to your finding the two closest lines, to bracket the value. But, do you really need to do that? INTERP1 will work perfectly well if you just input the entire grid of lines (and their corresponding Y values). MATLAB should find the closest line in the way you are trying to.

the cyclist

Subject: Strange rounding behaviour error?

From: Richard Crozier

Date: 26 Oct, 2009 14:04:05

Message: 5 of 6


Hey, thanks for the reply, I realised that the root of this would probably be along these lines, and have worked around this by simply rounding the numbers to 10 decimal places or so as more than this level of accuracy is not required in this particular application.

>
> Suppose I give you a bank account containing $1,000. Not bad, huh? Now I
> add $0.001 to your bank account. You don't really care about that, do you?
> Now what if I multiplied the contents of your bank account by 1000? Would
> you say that you had $1,000,000 or that you had $1,000,001?
>

In this case the analogy is more like I have gone to my bank manager and asked for a $1,000,000 loan and he has said he will give it to me only if I can prove I have MORE than $1,000,000 in the bank already. Therefore the extra $1 is rather crucial.

Thanks again,

Richard

Subject: Strange rounding behaviour error?

From: Richard Crozier

Date: 26 Oct, 2009 14:14:19

Message: 6 of 6


I would also like to add thanks to everyone else who replied with advice as well.

Cheers,

Richard

Tags for this Thread

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.

Contact us