Re: python math problem

Discussion in 'Python' started by Dennis Lee Bieber, Feb 15, 2013.

  1. On Fri, 15 Feb 2013 15:23:29 -0500, Kene Meniru <>
    declaimed the following in gmane.comp.python.general:

    > Joel Goldstick wrote:
    >
    > >
    > > This is not a string, it is scientific notion for 1.53... times 10 to the
    > > -15th power. Because of rounding errors caused by doing floating point
    > > math on in binary, you get a very small number instead of 0.
    > >

    >
    > I was just doing some testing and it was not equating to zero. Perhaps if I
    > rounded it up I may be more successful.


    Classical CompSci teachings when working with floating point numbers
    is to NEVER compare for equality. Instead one should compare against
    some epsilon:

    if x == y: #don't do

    if abs(x - y) < epsilon: #do this

    In your situation, "y" would be 0.0, so the test condenses to

    if abs(x) < epsilon:

    and a possible epsilon may be 1.0E-14

    --
    Wulfraed Dennis Lee Bieber AF6VN
    HTTP://wlfraed.home.netcom.com/
     
    Dennis Lee Bieber, Feb 15, 2013
    #1
    1. Advertising

  2. Dennis Lee Bieber wrote:

    > Classical CompSci teachings when working with floating point numbers
    > is to NEVER compare for equality. Instead one should compare against
    > some epsilon:


    "Don't compare floats for equality" is reasonably good advice.

    Adding "never" to that advice, especially when shouting as you do, moves it
    into the category "superstition".

    Consider:

    - Python floating point integers are exact for entire range of -2**53
    to 2**53, or about -9 million million to +9 million million; if you
    are working with floats that have integral values in this range,
    testing for equality is perfectly fine.

    - If you work exclusively with fractional powers of two, such as 1/2,
    1/4, 1/8, 1/16, etc. floats are typically exact.

    - Testing against an epsilon raises as many problems as it solves:

    + What epsilon should I pick? How do I know if my epsilon is too small,
    and therefore I'm rejecting values that I should accept, or too large,
    and so I'm accepting values I should reject?

    + If my epsilon is too small, calculating "abs(x - y) <= epsilon" is
    exactly equivalent to "x == y", only slower.

    + Should I test for absolute error, or relative error?

    + If relative error, how do I deal with values around zero where
    division is likely to introduce excessive rounding error?

    + Not to mention the risk of dividing by zero.

    - And how do I deal with INFs?

    py> x = float('inf')
    py> x == x
    True
    py> abs(x - x) <= 1e-14
    False



    --
    Steven
     
    Steven D'Aprano, Feb 16, 2013
    #2
    1. Advertising

  3. On Sat, 16 Feb 2013 15:49:12 +1100, Steven D'Aprano
    <> declaimed the following in
    gmane.comp.python.general:

    <snip>
    > Consider:
    >
    > - Python floating point integers are exact for entire range of -2**53
    > to 2**53, or about -9 million million to +9 million million; if you
    > are working with floats that have integral values in this range,
    > testing for equality is perfectly fine.
    >
    > - If you work exclusively with fractional powers of two, such as 1/2,
    > 1/4, 1/8, 1/16, etc. floats are typically exact.
    >
    > - Testing against an epsilon raises as many problems as it solves:
    >
    > + What epsilon should I pick? How do I know if my epsilon is too small,
    > and therefore I'm rejecting values that I should accept, or too large,
    > and so I'm accepting values I should reject?
    >
    > + If my epsilon is too small, calculating "abs(x - y) <= epsilon" is
    > exactly equivalent to "x == y", only slower.
    >
    > + Should I test for absolute error, or relative error?
    >
    > + If relative error, how do I deal with values around zero where
    > division is likely to introduce excessive rounding error?
    >
    > + Not to mention the risk of dividing by zero.
    >
    > - And how do I deal with INFs?


    Fine...

    The take-away then becomes: One must know how floating point is
    implemented in the computer in use (granted, practically everything is
    now using IEEE specifications vs my college mainframe with its radix-16
    format); and one must be cognizant of their problem domain to analyze
    when guards must be taken for comparison of equality.

    Since my "real world" experience has been in applications which are
    not integral or powers-of-two number-crunching then an epsilon
    comparison is pretty much a requirement -- especially when
    transcendental functions are involved. Yes, one has to then evaluate the
    problem domain to determine "how close is close enough".

    The recommendation to always use an epsilon comparison for floating
    point equality is a short phrase, and should trigger the needed analysis
    to determine what epsilon is suitable for that comparison.

    Or should Python implement REXX's NUMERIC statement? There is a can
    of worms (I'm not even sure Regina REXX implements it correctly --
    unless it is rounding to "digits" before applying "fuzz")

    /* */

    do D = 3 to 6
    numeric digits D
    do F = 0 to 3
    if D <> F then
    do
    numeric fuzz F
    call compare
    end
    end
    end
    exit

    compare:
    say "Digits:" digits() "Fuzz:" fuzz()
    say
    say '12345 = 12346 ' (12345 = 12346)
    say '12345 = 12356 ' (12345 = 12356)
    say '12345 = 12335 ' (12345 = 12335)
    say '1234 = 1235 ' (1234 = 1235)
    say '123.45 = 123.46 ' (123.45 = 123.46)
    say '123.45 = 123.56 ' (123.45 = 123.56)
    say
    say

    E:\UserData\Wulfraed\My Documents>regina test.rx
    Digits: 3 Fuzz: 0

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 1
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 3 Fuzz: 1

    12345 = 12346 1
    12345 = 12356 1
    12345 = 12335 1
    1234 = 1235 1
    123.45 = 123.46 1
    123.45 = 123.56 1


    Digits: 3 Fuzz: 2

    12345 = 12346 1
    12345 = 12356 1
    12345 = 12335 1
    1234 = 1235 1
    123.45 = 123.46 1
    123.45 = 123.56 1


    Digits: 4 Fuzz: 0

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 4 Fuzz: 1

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 1
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 4 Fuzz: 2

    12345 = 12346 1
    12345 = 12356 1
    12345 = 12335 1
    1234 = 1235 1
    123.45 = 123.46 1
    123.45 = 123.56 1


    Digits: 4 Fuzz: 3

    12345 = 12346 1
    12345 = 12356 1
    12345 = 12335 1
    1234 = 1235 1
    123.45 = 123.46 1
    123.45 = 123.56 1


    Digits: 5 Fuzz: 0

    12345 = 12346 0
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 0
    123.45 = 123.56 0


    Digits: 5 Fuzz: 1

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 5 Fuzz: 2

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 1
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 5 Fuzz: 3

    12345 = 12346 1
    12345 = 12356 1
    12345 = 12335 1
    1234 = 1235 1
    123.45 = 123.46 1
    123.45 = 123.56 1


    Digits: 6 Fuzz: 0

    12345 = 12346 0
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 0
    123.45 = 123.56 0


    Digits: 6 Fuzz: 1

    12345 = 12346 0
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 0
    123.45 = 123.56 0


    Digits: 6 Fuzz: 2

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 0
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0


    Digits: 6 Fuzz: 3

    12345 = 12346 1
    12345 = 12356 0
    12345 = 12335 1
    1234 = 1235 0
    123.45 = 123.46 1
    123.45 = 123.56 0



    E:\UserData\Wulfraed\My Documents>


    --
    Wulfraed Dennis Lee Bieber AF6VN
    HTTP://wlfraed.home.netcom.com/
     
    Dennis Lee Bieber, Feb 16, 2013
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. chirs
    Replies:
    18
    Views:
    798
    Chris Uppal
    Mar 2, 2004
  2. AciD_X
    Replies:
    4
    Views:
    8,170
    Jonathan Turkanis
    Apr 1, 2004
  3. Mark Healey
    Replies:
    7
    Views:
    1,568
    Tim Prince
    May 22, 2006
  4. Philipp
    Replies:
    9
    Views:
    1,172
    Mark Space
    Jul 23, 2008
  5. VK
    Replies:
    15
    Views:
    1,313
    Dr J R Stockton
    May 2, 2010
Loading...

Share This Page