# Float numbers equality. Classic List Threaded 44 messages 123
Open this post in threaded view
|

## Float numbers equality.

 Hi,I'm writing some unit tests, where I compare numbers and I have problem with something like this: 300 * 0.07 == 21 => false.print (300 * 0.07, 21, 300 * 0.07 == 21) What is the best way, for test float equality?I consider to use tostring function:print (300 * 0.07, 21, tostring (300 * 0.07) == tostring (21)),But i wonder, maybe there is a better way, to compare something like this? Thanks for any response.-- Karol Drożak
Open this post in threaded view
|

## Re: Float numbers equality.

 Hi On 08/09/2013 12:53 PM, Karol Dro wrote: > > What is the best way, for test float equality? > You don't. If you really need to, you need to compare with epsilon: epsilon = X * 0.00001 XequalY = ((X - epsilon < Y) and (X + espilon > Y)) -- Thomas
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Karol Dro > What is the best way, for test float equality? > > I consider to use tostring function: > print (300 * 0.07, 21, tostring (300 * 0.07) == tostring (21)), For this kind of numbers I think this is the best option, especially since it's in a unit test. But you make sure you know why tests like 300 * 0.07 == 21 give false. Otherwise, tell us more about the problem you're trying to solve.
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Karol Dro On Friday, August 9, 2013, Karol Dro wrote:Hi,I'm writing some unit tests, where I compare numbers and I have problem with something like this:  300 * 0.07 == 21 => false.print (300 * 0.07, 21, 300 * 0.07 == 21) What is the best way, for test float equality?I consider to use tostring function:print (300 * 0.07, 21, tostring (300 * 0.07) == tostring (21)),But i wonder, maybe there is a better way, to compare something like this? Thanks for any response.-- Karol Drożak This is exactly the problem that I've been working with. My first attempt was to do it is to do the calculation in the same way as I did in the function, but that created a tight coupling.  The format("%.10f", x) method was the most reasonable, for my testing needs, because it allowed me to specify the precision that I needed.In the end, floats were too challenging to work with because my conversions were being rounded down or up, depending upon where the conversion was coming from and the size of the values. I decided to go with integers by using Luiz's lint64 package. I keep multiplying everything as long as possible and then deal with division at the last step. I mod the division if I need to know what the partial portion of the sample is.  I don't know your specific case and others made my same suggestion. I just couldn't help but chime in, given this has been my life for the last few days. :)-Andrew
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Karol Dro Hi! 2013/8/9 Karol Dro <[hidden email]>: > I'm writing some unit tests, where I compare numbers and I have problem with > something like this: > 300 * 0.07 == 21 => false. > print (300 * 0.07, 21, 300 * 0.07 == 21) > > What is the best way, for test float equality? > > I consider to use tostring function: > print (300 * 0.07, 21, tostring (300 * 0.07) == tostring (21)), > But i wonder, maybe there is a better way, to compare something like this? In short: Use a reasonable "epsilon". But excuse me for mentioning the usual hint: Do a search for "What Every Computer Scientist Should Know About Floating-Point Arithmetic". The document may be a bit lengthy and answer a few more questions than you have, but it tells the basic characteristics of floating point arithmetics including important points as cancellation and the IEEE standard. Regards, Matthias
Open this post in threaded view
|

## Re: Float numbers equality.

 On Fri, Aug 9, 2013 at 12:37 PM, Matthias Kluwe <[hidden email]> wrote: > Hi! > > 2013/8/9 Karol Dro <[hidden email]>: > >> I'm writing some unit tests, where I compare numbers and I have problem with >> something like this: >> 300 * 0.07 == 21 => false. >> print (300 * 0.07, 21, 300 * 0.07 == 21) >> >> What is the best way, for test float equality? >> >> I consider to use tostring function: >> print (300 * 0.07, 21, tostring (300 * 0.07) == tostring (21)), >> But i wonder, maybe there is a better way, to compare something like this? > > In short: Use a reasonable "epsilon". Slightly longer "in short" -- this means use something like: function float_equal(lhs, rhs, epsilon)     return math.abs(lhs - rhs) < epsilon end /s/ Adam
Open this post in threaded view
|

## Re: Float numbers equality.

 > function float_equal(lhs, rhs, epsilon) >     return math.abs(lhs - rhs) < epsilon > end As mentioned before, if you have to do this, you need to use *relative* error, not absolute error:       return math.abs(lhs - rhs) < epsilon*rhs Floating-poin numbers are not distributed uniformily in their range; there's lot of clustering and empty intervals, due to scaling.
Open this post in threaded view
|

## Re: Float numbers equality.

 On Fri, Aug 9, 2013 at 3:18 PM, Luiz Henrique de Figueiredo <[hidden email]> wrote: >> function float_equal(lhs, rhs, epsilon) >>     return math.abs(lhs - rhs) < epsilon >> end > > As mentioned before, if you have to do this, you need to use *relative* error, > not absolute error: >       return math.abs(lhs - rhs) < epsilon*rhs > > Floating-poin numbers are not distributed uniformily in their range; > there's lot of clustering and empty intervals, due to scaling. > Ah, whoops, yeah, you're right, I got sloppy there. Really that ought to be epsilon*math.max(lhs,rhs) even. /s/ Adam
Open this post in threaded view
|

## Re: Float numbers equality.

 On Fri, Aug 9, 2013 at 3:47 PM, Coda Highland <[hidden email]> wrote: > On Fri, Aug 9, 2013 at 3:18 PM, Luiz Henrique de Figueiredo > <[hidden email]> wrote: >>> function float_equal(lhs, rhs, epsilon) >>>     return math.abs(lhs - rhs) < epsilon >>> end >> >> As mentioned before, if you have to do this, you need to use *relative* error, >> not absolute error: >>       return math.abs(lhs - rhs) < epsilon*rhs >> >> Floating-poin numbers are not distributed uniformily in their range; >> there's lot of clustering and empty intervals, due to scaling. >> > > Ah, whoops, yeah, you're right, I got sloppy there. Really that ought > to be epsilon*math.max(lhs,rhs) even. > > /s/ Adam Er. Actually, I just need to get some sleep. It doesn't matter which side you multiply by there because if the two terms are close enough that an epsilon comparison is necessary in the first place then you're going to get basically the same result. I don't usually need to do that kind of order-of-magnitude scaling because my epsilon comparisons are with code where I already know the range of the numbers involved. /s/ Adam
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Coda Highland On 10/08/2013 0.47, Coda Highland wrote: > Ah, whoops, yeah, you're right, I got sloppy there. Really that ought > to be epsilon*math.max(lhs,rhs) even. Do you mean epsilon*math.max(math.abs(lhs),math.abs(rhs)) ? --    Enrico
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Luiz Henrique de Figueiredo On Sat, Aug 10, 2013 at 1:18 AM, Luiz Henrique de Figueiredo wrote: > function float_equal(lhs, rhs, epsilon) >     return math.abs(lhs - rhs) < epsilon > end As mentioned before, if you have to do this, you need to use *relative* error, not absolute error:       return math.abs(lhs - rhs) < epsilon*rhs Two zeros will never be equal to each other :-(  Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Karol Dro > What is the best way, for test float equality? Since everybody else is clearly expert enough not worry about the following point, I suppose it does not need mentioning. But still … Once you have a satisfactory `float_eq` function, don't think that debug.setmetatable(0.0,{__eq=float_eq}) will hencefore allow you to test `if a==b` by that metamethod. Please do not think that.
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Enrico Colombini On Sat, Aug 10, 2013 at 12:48 AM, Enrico Colombini <[hidden email]> wrote: > On 10/08/2013 0.47, Coda Highland wrote: >> >> Ah, whoops, yeah, you're right, I got sloppy there. Really that ought >> to be epsilon*math.max(lhs,rhs) even. > > > Do you mean epsilon*math.max(math.abs(lhs),math.abs(rhs)) ? > > -- >   Enrico > No, but you have a good point that it should be math.abs(epsilon*rhs). /s/ Adam
Open this post in threaded view
|

## Re: Float numbers equality.

 Given that this subject comes up every couple of months, and that there are some subtleties to it, that this warrants a new function in the math library to do it the right way? On Aug 10, 2013, at 9:04 AM, Coda Highland <[hidden email]> wrote: > On Sat, Aug 10, 2013 at 12:48 AM, Enrico Colombini <[hidden email]> wrote: >> On 10/08/2013 0.47, Coda Highland wrote: >>> >>> Ah, whoops, yeah, you're right, I got sloppy there. Really that ought >>> to be epsilon*math.max(lhs,rhs) even. >> >> >> Do you mean epsilon*math.max(math.abs(lhs),math.abs(rhs)) ? >> >> -- >>  Enrico >> > > No, but you have a good point that it should be math.abs(epsilon*rhs). > > /s/ Adam >
Open this post in threaded view
|

## Re: Float numbers equality.

 On Aug 10, 2013, at 3:08 PM, Tim Hill wrote: [context: > for i=1,78 do s="." if (i*0.1)*10~=i then s="X" end io.write(s) end print() ..X..XX....X.X........XX...XX...........X....X.X..X.X..X.X..X.X............... ] > Given that this subject comes up every couple of months, and that there are some subtleties to it, that this warrants a new function in the math library to do it the right way? The criteria for inclusion in the standard Lua library aren't clear to me. The module system is there since it's a minimal thing everybody needs to coordinate on. Is that true of this? Much of the library seems to be important functionality for everyday use which cannot be implemented outside C, at least efficiently. That's definitely not true of equals_within_epsilon, so that suggests the place it would go is Microlight. Maybe. Some people, including me, wish that more of _PiL_ were in the manual. But I'm not volunteering to write the gloss. Jay
Open this post in threaded view
|

## Re: Float numbers equality.

 In reply to this post by Tim Hill > Given that this subject comes up every couple of months, and that there are some subtleties to it, that this warrants a new function in the math library to do it the right way? I don't think so. Floating-point arithmetic is not simple. I think it'd be a disservice to try to hide its complexities in a official function that may give the impression that it solves the problem reliably, when it can't. On the other hand, there is nothing instrinsically wrong with floating-point equality. The only catches come from numbers that should be equal but are computed in two different ways and from naive expectations such as 300 * 0.7 == 21, due to a misunderstanding that floating-point representation is a binary one, not a decimal one.
Open this post in threaded view
|

## Re: Float numbers equality.

 On Saturday, August 10, 2013, Luiz Henrique de Figueiredo wrote:> Given that this subject comes up every couple of months, and that there are some subtleties to it, that this warrants a new function in the math library to do it the right way? I don't think so. Floating-point arithmetic is not simple. I think it'd be a disservice to try to hide its complexities in a official function that may give the impression that it solves the problem reliably, when it can't. On the other hand, there is nothing instrinsically wrong with floating-point equality. The only catches come from numbers that should be equal but are computed in two different ways and from naive expectations such as 300 * 0.7 == 21, due to a misunderstanding that floating-point representation is a binary one, not a decimal one.In an effort to understand (not debate), where would:       return math.abs(lhs - rhs) < epsilon*rhs ...be unsuitable? Imagine that I'm dealing with float equality and it isn't working. Also imagine that I don't know very much about the issue.  I dig into the math library and find a function that does this.  How am I likely to be confused further? What knowledge would I still lack that would keep me from understanding, provided that PiL offered some additional context? As a post script, I took the advice found in Programming In Lua and found myself utterly lost (although ever so slightly closer to my Calculus Through Googling degree). I read the part of the discussion related to the epsilon, but since so much of it was aimed at an audience that wasn't me, I failed to identify the solution.  As a result, I believe that once I feel like I understand the common issues, I should (or someone like me should) write a wiki on it. I was unable to find a really good document aimed at someone who can't read calculus notation. Several Microsoft articles came very close, however.  - Andrew
Open this post in threaded view
|

## Re: Float numbers equality.

 In case rhs < 0 ----- Original Message ----- From: [hidden email] Sent: Sunday, August 11, 2013 5:19 PM Subject: Re: Float numbers equality. On Saturday, August 10, 2013, Luiz Henrique de Figueiredo wrote: > Given that this subject comes up every couple of months, and that there are some subtleties to it, that this warrants a new function in the math library to do it the right way?I don't think so. Floating-point arithmetic is not simple. I think it'd bea disservice to try to hide its complexities in a official function thatmay give the impression that it solves the problem reliably, when it can't.On the other hand, there is nothing instrinsically wrong with floating-pointequality. The only catches come from numbers that should be equal but arecomputed in two different ways and from naive expectations such as300 * 0.7 == 21, due to a misunderstanding that floating-point representationis a binary one, not a decimal one. In an effort to understand (not debate), where would:        return math.abs(lhs - rhs) < epsilon*rhs ...be unsuitable? Imagine that I'm dealing with float equality and it isn't working. Also imagine that I don't know very much about the issue.  I dig into the math library and find a function that does this.  How am I likely to be confused further? What knowledge would I still lack that would keep me from understanding, provided that PiL offered some additional context? As a post script, I took the advice found in Programming In Lua and found myself utterly lost (although ever so slightly closer to my Calculus Through Googling degree). I read the part of the discussion related to the epsilon, but since so much of it was aimed at an audience that wasn't me, I failed to identify the solution.  As a result, I believe that once I feel like I understand the common issues, I should (or someone like me should) write a wiki on it. I was unable to find a really good document aimed at someone who can't read calculus notation. Several Microsoft articles came very close, however.  - Andrew
Open this post in threaded view
|

## Re: Float numbers equality.

 2013/8/11 Victor Bombi <[hidden email]>: > In case rhs < 0 True, but one we know what Andrew means. > ----- Original Message ----- > From: Andrew Starks > > In an effort to understand (not debate), where would: > >        return math.abs(lhs - rhs) < epsilon*rhs > > ...be unsuitable? Suppose lhs and rhs are both sums of many terms of both signs, and the total is close to zero, in theory might even be equal to zero. The above test may well not be satisfied when actually the numbers are equal on paper. Instead, one should be using      return math.abs(lhs - rhs) < epsilon*scale where 'scale' is a rough approximation to the sums of the absolute values. There are other situations. You can't fix epsilon by looking at machine precision: the more computations it takes to compute the operands, the bigger epsilon should be, etc. Luiz is right here: the appropriate test for floating-point equality is never so simple that any one method is always foolproof. There is no substitute for consulting an experienced numerical analyst. :-)