Compare, two identical numbers are not the same?!

Discussion in 'Perl Misc' started by Justin C, Jun 29, 2009.

  1. Justin C

    Justin C Guest

    This one is really confusing me. I have a comparison:

    $totalIndividualWeights != $param{weight}

    and when they're both 42.6 (probably other numbers too, but this is the
    problem someone has, and has come to me with) Perl says they're not the
    same:

    my $totalIndividualWeights = addIndividualWeights();

    if ($totalIndividualWeights != $param{weight}){
    print "Weight does not add up to total weight given on the first form.\$totalIndividualWeights = $totalIndividualWeights \n \$param{weight} = $param{weight}";
    }

    The print statement says both weights are 42.6. $param{weight} was
    input by the user, $totalIndividualWeights is reached by adding several
    user inputs: 2.86, 9.94, 9.98, 9.88, 9.94

    Does perl have a problem with empty decimal places? What I mean is, the
    inputs are to two decimals, but the result is only using one, is perl
    thinking "42.60" and not matching 42.6?

    Thank you for any help you can give with this.

    Justin.

    --
    Justin C, by the sea.
     
    Justin C, Jun 29, 2009
    #1
    1. Advertising

  2. Justin C <> wrote:
    >
    >This one is really confusing me. I have a comparison:
    >
    >$totalIndividualWeights != $param{weight}
    >
    >and when they're both 42.6 (probably other numbers too, but this is the
    >problem someone has, and has come to me with) Perl says they're not the
    >same:


    You forgot the first commandment of computer numerics:

    Thou shalt not use equality for floating point numbers!

    See 'perldoc -q 9999' for further details. Although those seem to be
    unrelated questions/issues in fact they have the same underlying reason
    which applies to virtually all programming languages.

    >The print statement says both weights are 42.6


    Try printing them with 20 digits:
    printf("%.20f", $totalIndividualWeights)
    You may be surprised.

    jue
     
    Jürgen Exner, Jun 29, 2009
    #2
    1. Advertising

  3. Glenn Jackman <> wrote:
    >At 2009-06-29 12:24PM, "Justin C" wrote:
    >> The print statement says both weights are 42.6. $param{weight} was
    >> input by the user, $totalIndividualWeights is reached by adding several
    >> user inputs: 2.86, 9.94, 9.98, 9.88, 9.94

    >
    >I addition to all the better advice, did you chomp() your user input?
    >Are you comparing "42.6\n" to a number that's close to 42.6?


    If that were the case then he should have gotten a warning about
    non-numerical value used in numerical comparison. At least if he had
    used warnings.

    Technically it doesn't matter. He is using numerical compare "=", thus
    Perl uses the arguments in numerical context and therefore automatically
    converts the string "42.6\n" into the numerical floating point value
    42.6 resp. something very close to it.

    jue
     
    Jürgen Exner, Jun 30, 2009
    #3
  4. Tad J McClellan <> wrote:
    >Jürgen Exner <> wrote:
    >> Glenn Jackman <> wrote:
    >>>At 2009-06-29 12:24PM, "Justin C" wrote:
    >>>> The print statement says both weights are 42.6. $param{weight} was
    >>>> input by the user, $totalIndividualWeights is reached by adding several
    >>>> user inputs: 2.86, 9.94, 9.98, 9.88, 9.94
    >>>
    >>>I addition to all the better advice, did you chomp() your user input?

    >
    >> If that were the case then he should have gotten a warning about
    >> non-numerical value used in numerical comparison. At least if he had
    >> used warnings.

    >
    >No, there is no warning for trailing whitespace.


    I stand corrected.

    jue
     
    Jürgen Exner, Jun 30, 2009
    #4
  5. Justin C

    Justin C Guest

    On 2009-06-29, Jürgen Exner <> wrote:
    > Justin C <> wrote:
    >>
    >>This one is really confusing me. I have a comparison:
    >>
    >>$totalIndividualWeights != $param{weight}
    >>
    >>and when they're both 42.6 (probably other numbers too, but this is the
    >>problem someone has, and has come to me with) Perl says they're not the
    >>same:

    >
    > You forgot the first commandment of computer numerics:
    >
    > Thou shalt not use equality for floating point numbers!


    Being self-taught this had passed me by (I'm not qualified to teach
    Perl you see, that's why my education was lacking this nugget - among
    others).

    OK. I can be certain that a user will never put in a number using more
    than two decimal places - if they do I can reject it. Would I be better
    off multiplying the input data by 100 and working in integars only? Then
    dividing by 100 only when I need the "real" number? It sure looks like
    it would make life easier.

    On the other hand, the sprintf trick works. Maybe I should just try and
    remember not to compare floats - that's obviously the best solution
    because it'll save me asking again in the future.

    Maybe, when I write my end of term report for myself, I should mention
    this, maybe I'll remember it when I read what my teacher says about me.


    > See 'perldoc -q 9999' for further details. Although those seem to be
    > unrelated questions/issues in fact they have the same underlying reason
    > which applies to virtually all programming languages.
    >
    >>The print statement says both weights are 42.6

    >
    > Try printing them with 20 digits:
    > printf("%.20f", $totalIndividualWeights)
    > You may be surprised.


    Not *that* surprised. :) (at least, not after reading this thread!).


    Justin.

    --
    Justin C, by the sea.
     
    Justin C, Jun 30, 2009
    #5
  6. Justin C

    ccc31807 Guest

    On Jun 30, 10:17 am, Justin C <> wrote:
    > OK. I can be certain that a user will never put in a number using more
    > than two decimal places - if they do I can reject it. Would I be better
    > off multiplying the input data by 100 and working in integars only?


    Test that the absolute value of the difference between the two is less
    than, say, 0.001, or whatever your tolerance is. You can create a user
    defined function that returns true or false for your convenience, like

    if (within_tolerance( val1, val2)) #if true
    { then_do_something(); }
    else #if false
    { do_something_else(); }

    CC
     
    ccc31807, Jun 30, 2009
    #6
  7. Justin C <> wrote:
    >On 2009-06-29, Jürgen Exner <> wrote:
    >> You forgot the first commandment of computer numerics:
    >>
    >> Thou shalt not use equality for floating point numbers!

    >
    >OK. I can be certain that a user will never put in a number using more
    >than two decimal places - if they do I can reject it. Would I be better
    >off multiplying the input data by 100 and working in integars only?


    That would be one common approach to avoid any inaccuracies caused by
    floating point arithmetic.

    >Then
    >dividing by 100 only when I need the "real" number? It sure looks like
    >it would make life easier.


    Think of it as doing all calculations in cent instead of in dollar or
    euro and only convert them into a 'human-friendly" format when printing
    or reading those amounts.
    If this works for your application then it's the best posible solution.

    However, computer numerics are tricky, there is a reason why it is a
    subject matter at university, and even that method is not fool-proof.

    Example: when calculating interest on a long list of accounts, even if
    you manage them internally in cent, you may get a different result when
    adding up all the interest paid to each account compared to calculating
    the sum of all accounts and then the interest on the lump sum. Those
    rounding errors are what's driving accountants and bankers nuts because
    it takes forever to find out where and why those 3 cents went missing in
    action while the missing million will be spotted immediately.

    >On the other hand, the sprintf trick works. Maybe I should just try and
    >remember not to compare floats -


    It is ok to compare floats for smaller/larger. But instead of checking
    for equal you must check if the difference between the two numbers is
    smaller than some tiny number. How large that tiny number is depends on
    your application area, but it will never be 100% accurate.

    jue
     
    Jürgen Exner, Jun 30, 2009
    #7
  8. Justin C

    Justin C Guest

    On 2009-06-30, Jürgen Exner <> wrote:
    > Justin C <> wrote:
    >>On 2009-06-29, Jürgen Exner <> wrote:
    >>> You forgot the first commandment of computer numerics:
    >>>
    >>> Thou shalt not use equality for floating point numbers!

    >>
    >>OK. I can be certain that a user will never put in a number using more
    >>than two decimal places - if they do I can reject it. Would I be better
    >>off multiplying the input data by 100 and working in integars only?

    >
    > That would be one common approach to avoid any inaccuracies caused by
    > floating point arithmetic.


    I'll try and remember this for another time I might need it.


    >>On the other hand, the sprintf trick works. Maybe I should just try and
    >>remember not to compare floats -

    >
    > It is ok to compare floats for smaller/larger. But instead of checking
    > for equal you must check if the difference between the two numbers is
    > smaller than some tiny number. How large that tiny number is depends on
    > your application area, but it will never be 100% accurate.


    Thank you, Jurgen and CC. I'm doing a straight compare of two sprintf
    'numbers', but I quite like the idea of testing the difference - a
    tollerance as CC put it. I might re-write the code for proof of concept,
    and "doing it" actually gets it into my head better than reading it.

    Justin.

    --
    Justin C, by the sea.
     
    Justin C, Jul 2, 2009
    #8
  9. Justin C

    Guest

    On Thu, 02 Jul 2009 22:48:58 -0000, Justin C <> wrote:

    >On 2009-06-30, Jürgen Exner <> wrote:
    >> Justin C <> wrote:
    >>>On 2009-06-29, Jürgen Exner <> wrote:
    >>>> You forgot the first commandment of computer numerics:
    >>>>
    >>>> Thou shalt not use equality for floating point numbers!
    >>>
    >>>OK. I can be certain that a user will never put in a number using more
    >>>than two decimal places - if they do I can reject it. Would I be better
    >>>off multiplying the input data by 100 and working in integars only?

    >>
    >> That would be one common approach to avoid any inaccuracies caused by
    >> floating point arithmetic.

    >
    >I'll try and remember this for another time I might need it.
    >
    >
    >>>On the other hand, the sprintf trick works. Maybe I should just try and
    >>>remember not to compare floats -

    >>
    >> It is ok to compare floats for smaller/larger. But instead of checking
    >> for equal you must check if the difference between the two numbers is
    >> smaller than some tiny number. How large that tiny number is depends on
    >> your application area, but it will never be 100% accurate.

    >
    >Thank you, Jurgen and CC. I'm doing a straight compare of two sprintf
    >'numbers', but I quite like the idea of testing the difference - a
    >tollerance as CC put it. I might re-write the code for proof of concept,
    >and "doing it" actually gets it into my head better than reading it.
    >
    > Justin.


    The ballpark for comparisons are C functions ceil/floor (posix in perl).
    Never can you compare doubles for equality, and never can you even see a
    print of thier actual float value.

    There is only one need for true comparisons, the is the case of
    Numerical Methods absolute "difference" being less/greater than some
    value. Or in the case of rounding is needed (ala the Pentium 60 bug
    where zero is less than some absolute value of some really small fraction
    of 1).

    -sln
     
    , Jul 4, 2009
    #9
    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. Harald Kirsch
    Replies:
    4
    Views:
    17,514
    Dale King
    Apr 15, 2006
  2. GenxLogic
    Replies:
    3
    Views:
    1,285
    andrewmcdonagh
    Dec 6, 2006
  3. Neroku
    Replies:
    12
    Views:
    559
    Oliver Wong
    Feb 12, 2007
  4. Replies:
    7
    Views:
    657
  5. Replies:
    11
    Views:
    290
Loading...

Share This Page