SKILL : should the order matter for the plus function

Discussion in 'Cadence' started by Suresh Jeevanandam, Mar 3, 2005.

  1. After debugging my code for an hour, I found that the sum of a list of
    numbers can be *different* based on the order in SKILL !!!

    When I enter,
    (-22m + 2m + 2m + 2m + 2m + 14m )
    => 6.938894e-18

    (-22m + 2m + 2m + 2m + 2m + 14m ) == 0.0
    => nil

    (2m + 2m + 2m + 2m + 14m - 22m )
    => 0.0

    (2m + 2m + 2m + 2m + 14m - 22m ) == 0.0
    => t

    Any Idea how to get 0.0 irrespective of the order.

    Regards,
    Suresh
     
    Suresh Jeevanandam, Mar 3, 2005
    #1
    1. Advertisements

  2. That's an expected effect of using floating point numbers.

    Probably the most cited paper introducing the subject:

    http://citeseer.ist.psu.edu/goldberg91what.html

    (You can download the paper using the links at upper right).
    Don't use floating point numbers.

    Yours,
     
    Jean-Marc Bourguet, Mar 3, 2005
    #2
    1. Advertisements

  3. A simple solution I found is to replace all the lines
    from
    lhs == 0.0
    to
    abs(lhs) < 1n

    ( If 1n is negligible in the comparison ).

    Regards,
    Suresh
     
    Suresh Jeevanandam, Mar 3, 2005
    #3
  4. Suresh Jeevanandam

    Guest Guest

    With floating point you cannot.

    When doing floating point compares, you should always do "fuzzy" compares.
    Figure out your desired accuracy and compare within that.

    For example:

    MyDeviation = 1.0e-6
    MyResult = <calculation>
    MyComparator = 0.0
    if( abs(MyResult - MyComparator) < MyDeviation
    then
    ;equal within MyDeviation range of accuracy
    t
    else
    ;not equal within MyDeviation range of accuracy
    nil
    )

    Note that this is standard practice when dealing with floating point, since
    floating point is by definition not totally accurate.

    -Pete Zakel
    ()

    "Most turkeys taste better the day after; my mother's tasted better the day
    before."
    -Rita Rudner
     
    Guest, Mar 4, 2005
    #4
  5. Suresh Jeevanandam

    Jim Newton Guest

    Hi Pete, i think you'll find the same results if you rewrite
    your program in C, Perl, Java, Python, Fortran or almost
    any language. What would you like the language to do
    with the round off error? 2/1000 is not epxressable
    exactly with a finite number of decimal places in binary.

    The only way to assure that you get zero when you calculate
    this is to handle the round off yourself; don't leave it
    up to the language. For example, you can choose a grid
    say grid=1.0/1000 and you do not care how that is
    represented in binary.

    Then before applying the + operator, round all the numbers
    to the nearest grid, then after adding up, round the
    result to the nearest grid.


    (procedure (add_numbers_on_grid n_grid l_numbers)
    ;; first express the numbers in terms of the given grid
    l_numbers = (foreach mapcar num l_numbers
    (round num / n_grid))
    ;; then add up the integers and multiply by grid
    n_grid * (apply 'plus l_numbers))

    I think you'll find that the function add_numbers_on_grid
    will add up your numbers in any order the same way.

    Note that (apply 'plus l_numbers) will add up a list of number
    but only works for lists of length 2 or more. The function
    will not work for adding up zero or 1 numbers.

    (add_numbers_on_grid l_numbers 1m '( -22m 2m 2m 2m 2m 14m)) ==> 0.0

    (add_numbers_on_grid l_numbers 1m '( 2m 2m 2m 2m 14m -22m)) ==> 0.0


    Hope this helps.
    -jim
     
    Jim Newton, Mar 6, 2005
    #5
  6. Instead, the standard cadence functions to compare can take an
    additional optional argument 'accuracy'.
    so that we get

    equal(plus(-22m 8m 14m) 0.0)
    => nil

    equal(plus(-22m 8m 14m) 0.0 1n) ; This is the proposed way, the third
    argument is the optional accuracy.
    => t

    I think this should be more efficient, any comments..

    Regards,
    Suresh
     
    Suresh Jeevanandam, Mar 7, 2005
    #6
  7. Other languages don't have this - why not simply write a function yourself to
    do this?

    Different applications will have different ideas on how equal something should
    be. Personally I would probably use a relative tolerance together with a
    smaller absolute tolerance). That allows you to cope with numbers very close
    to zero, without running out of headroom.

    But for some applications that would be overkill - a simple absolute tolerance
    would be sufficient.

    (a note on terminology here - a relative tolerance would be some fraction of
    the numbers involved in the comparison; an absolute tolerance is a fixed
    number).

    Andrew.
     
    Andrew Beckett, Mar 7, 2005
    #7
  8. Suresh Jeevanandam

    Jim Newton Guest

    Hi suresh, what would you like the equal function to
    do if you pass it strings, or other data types?

    equal("abc" "ABC" 1n)
    equal("plus(1 2)" "3" 0.0)
    equal('(1 2 3) '(1.0 2.00000001 3) 1m)

    ?
     
    Jim Newton, Mar 8, 2005
    #8
  9. The optional argument should be ignored because its meaningless :)

    Regards,
    Suresh
     
    Suresh Jeevanandam, Mar 9, 2005
    #9
  10. Other languages are used by professional hackers and they may have
    custom library to do these kind of common jobs.
    But SKILL is used by people whose main job is not programming. Most of
    the people would tend to use the == operator with the floating point
    values too.
    I think almost everybody would have to compare floating point numbers in
    their scripts at some point of time. If all the people need to write the
    same function why not implement it as part of the language itself.
    If there are multiple solutions lets identify those most common stuffs
    and implement only those.
    In almost 90% of the cases either absolute or relative tolerance would
    be fine.

    Also, in most of the other languages only operators are available. In
    skill we have both == operator and the equivalent function.

    We can make either absolute tolerance or relative tolerance or both as
    the standard functions. ( In the third case we would require an
    additional optional boolean argument to indicate absolute/relative
    tolerance)

    Lets put atleast one of these into the standard function. Let the user
    write his own function any other way of dealing this problem.)


    Regards,
    Suresh
     
    Suresh Jeevanandam, Mar 9, 2005
    #10
    1. Advertisements

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.