in reply to Re^3: Problem with a sort result
in thread Problem with a sort result

Looks to me like it's an integer/bigint problem: 9 digits:
perl -E' $h={foo=>{bar=>10000000000},baz=>{bar=>70000000},qux=>{bar=>2000000000 +0}}; say "$_: $h->{$_}->{bar}" for sort { eval { say $h->{$b}->{bar}. " - " +.$h->{$a}->{bar}." = ".($h->{$b}->{bar} - $h->{$a}->{bar}); $h->{$b}- +>{bar} - $h->{$a}->{bar} } } keys %$h; ' 10000000000 - 70000000 = 9930000000 20000000000 - 10000000000 = 10000000000 qux: 20000000000 foo: 10000000000 baz: 70000000
the expected output is correct. 12 digits:
perl -E' $h={foo=>{bar=>10000000000000},baz=>{bar=>70000000},qux=>{bar=>2000000 +0000000}}; say "$_: $h->{$_}->{bar}" for sort { eval { say $h->{$b}->{bar}. " - " +.$h->{$a}->{bar}." = ".($h->{$b}->{bar} - $h->{$a}->{bar}); $h->{$b}- +>{bar} - $h->{$a}->{bar} } } keys %$h; ' 20000000000000 - 70000000 = 19999930000000 10000000000000 - 70000000 = 9999930000000 foo: 10000000000000 baz: 70000000 qux: 20000000000000
incorrect ordering.


Replies are listed 'Best First'.
Re^5: Problem with a sort result: weird subtraction behaviour?
by Discipulus (Canon) on Jan 15, 2016 at 09:00 UTC
    Infact it is something strange: while in motorbike this morning i thought i was wrong (in my previous post): the results of subtraction must be valid too when sorting: big minus less is greater than zero; equal minus equal is 0 and little minus big is less than zero:
    perl -e "print join qq(\n),sort {$a - $b} @ARGV" 33 1 2 99 1 2 33 99 # same result using <=> or -
    using big nums give me incorrect ordering using subtraction when one number is ten digits or more:
    perl -e "print join qq(\n),sort {$a - $b} @ARGV" 10000000000 3 2 10000000000 2 3

    There are no rules, there are no thumbs..
    Reinvent the wheel, then learn The Wheel; may be one day you reinvent one of THE WHEELS.

      Discipulus, rdfield, you are both correct: This is a problem with long integers.

      What I don't understand is: Why are the integers correctly remembered, correctly displayed, but incorrectly compared to 0 ? Because, let's face it, it's the core of the problem:

      When it's a "small" number, it is correctly evaluated as positive, negative, or null.

      When it is a "big" number, then there may be problems in evaluating the sign. Much like if some bit from the big number was used as a sign bit, or whatever, where the real good practice would merely be to check the sign at the start of the number string...

      I mean, if it starts with a "+" or a digit, then it's positive. If it starts with a "-", it's negative. We keep that "sign", unless all digits are 0 -> in which case it is merely null.

      Did I miss something, there ?

        The problem is that the code that implements the behaviour is in C. There's no number string, there are different integer types with different byte sizes.
        ($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord }map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,