round(0.5) returns 0

Issue #636 open
Former user created an issue

SpeedCrunch master-a091763c26002bc3fa4597c98ca8f1c229f3dde7 (Portable Edition) (Qt 5.5.0), Windows 7 64-bit.

round(0.5) returns 0. round(1/2) returns 0.

I believe it must be 1.

Comments (26)

  1. Pol Welter

    This comes from floatcommon.c, line 367:

        if (digit < 5 || (digit == 5 && float_getlength(x) == 1))
          value = 0;
    

    I have no idea what this second condition is good for. Someone must have been thinking something.

  2. Pol Welter

    AFAICT, it literally says: if the number is 0.5, round down. Weird.

    This also happens when doing round(0.05; 1) or similar.

  3. Felix Krull

    This condition has always been around in the "new" math engine (as in, introduced in bb03ae3f8df408 back in 2007). There's a justification in doc/legacy/new_engine.pdf, at the bottom of page 2:

    Second, 0.5, rounded to an integer, yields 0, not  1. This is conforming to international rounding rules, that say, if the cut off digit is a single 5 only,  rounding occurs such that the last digit of the rounded result is even. This eliminates a slight bias  against rounding down, that otherwise would be present. (Note: according to this rule, 1.5 is rounded  to 2).

    I haven't heard of that special case before, but that doesn't really mean anything. Still, it seems odd to me as well.

  4. Helder Correia repo owner

    I guess this is what the description refers to:

    This is the default rounding mode used in IEEE 754 computing functions and operators (see also Nearest integer function).

  5. Helder Correia repo owner

    What concerns me the most is the fact that we don't have a single test for this situation. I checked testfloatnum, testevaluator and testhmath. I'm honestly not sure which rounding method we should provide, but whichever it is, we should thoroughly document it.

  6. Pol Welter

    Oh... this 'Round half to even' thing makes sense. We should test and document this. Thanks for digging this up!

  7. Vitalii Dovgan

    Are there mistype(s) in the corresponding examples and unit tests? Taking into account that only round(0.5) results in rounding to 0, I can't understand the following below:

    +            round(12.345; 2)
    +            = 12.34 // shoudn't it be "12.35" ?
    

    And, anyway, doesn't such idea of rounding contradict with classical mathematics?

    And the following 1 line below:

    +    CHECK(HMath::round("0.5", 0), "0"); // OK (0.5 is rounded to 0)
    +    CHECK(HMath::round("1.5", 0), "2"); // OK
    +    CHECK(HMath::round("2.5", 0), "2"); // "2" ??? Shoudn't it be "3" ?
    +    CHECK(HMath::round("3.5", 0), "4"); // OK
    +    CHECK(HMath::round("-0.5", 0), "0"); // OK (-0.5 is rounded to -0)
    +    CHECK(HMath::round("-1.5", 0), "-2"); // OK
    
  8. Tey'

    @DV__ please read that part of the Wikipedia article. Basically, when there is a tie, it rounds to the nearest even integer.

    For the record, this is how the rounding in the C standard library printf() function behaves but not how round() from the same library does.

  9. Vitalii Dovgan

    My opinion: those people are mad. Mathematics used to be exact science - but with these "rounding adjustments" it's not. Let's say you want to calculate: 1. round(0.5) + round(2.5) + round(4.5) 2. round(1.5) + round(3.5) + round(5.5) With "classical" mathematics, you always get the exact results: 1. 9 2. 12 With the proposed "adjustments", you can get: 1. 6 or 9 2. 9 or 12 In terms of exact science, it's inadmissible!

  10. Pol Welter

    Rounding will always introduce an error, in particular when summing. Naturally you can always find a sequence where any strategy performs particularly poorly.

    The 'round to even' strategy minimizes bias for any sane distribution.

    Also, if you are rounding at all, things stop being an exact science by definition. ;)

    Finally I'd like to point out that if you really care about the error introduced by tie breaking rules, then you are rounding too much :)

    TL;DR: Let's leave SC the way it is.

  11. Pol Welter

    About your example: the 'exact' result is the one without any rounding at all. A highly desirable characteristic of a rounding operation is to preserve e.g. a sum. This is done much better by rounding to even. Your example perfectly illustrates this.

  12. Vitalii Dovgan

    My last comments. Maybe it could be an option? Because: 1) I don't see strong arguments why one would prefer rounding to odd to rounding to even; 2) in any case, this will blow someone's mind when rounding numbers with .5 at the end gives different results.

    Let's look at Python:

    >>> map(lambda x: round(x), (0.5, 1.5, 2.5, 3.5, 4.5))
    [1.0, 2.0, 3.0, 4.0, 5.0]
    

    So it uses a "classical" rule. IMHO, a simple mathematical engine by default should not deal with "banking rounding" and similar. Just because it's unexpected.

  13. Helder Correia repo owner

    I can honestly see both points here. SpeedCrunch tries to be SI-compliant, mathematically correct, and all that jazz. But myself had never heard of round-to-even before I found that Wikipedia page motivated by the reporting of this issue by Vitalii. I can see how confused the average user can become because of the default behavior we provide. l'd say we should modify round() by adding support to 3 or 4 rounding stategies (the default being the one Vitalii and most users would expect). The the behavior would happen according to the radio group option selected somewhere in the Settings menu. An alternative is to offer roundzero(), roundinf(), round() (alias for roundinf()), roundeven() and roundodd()

  14. Pol Welter

    I'm fine with any approach. The whole debate is indeed rather silly.

    FYI, in Matlab, round() rounds ties away from zero, while convergent() does the even thing.

    To be honest, I don't see the need to add more than one function, and definitely not another setting. I still think that if you are rounding to the point where this matters, you are rounding too much. Really, anyone algorithm is fine for me. I was just trying to motivate the round-to-even way :)

  15. Felix Krull

    I don't have any strong opinion either; that being said, rounding to infinity is probably the behaviour most people expect (it's certainly what I expected as well), I think we should switch to that (and explicitly document it). We can revisit the question of extra functions or a setting later IMO.

    (I do think a setting would be better because it would also control what rounding you get when using an explicit decimal precision setting.)

  16. Tey'

    I also like the user setting proposal with the default set to round tie to infinity or zero, but not to even or odd (these rounding logic do not sound natural to me, even though I understand why they exist now).

    Speaking of user settings, since the settings menu is getting more and more populated, is there a plan to put them in a settings dialog some day?

  17. Log in to comment