http://qs1969.pair.com?node_id=1116952


in reply to 64-bit division anomolies (Solved.)

A Pure Perl work-around:
#!/use/bin/perl use strict; use warnings; sub udiv64 { my ($a, $b) = @_; return 0 if $b > $a; my $c = $a >> 1; my $d = do { use integer; $c / $b }; my $e = $a - (do { use integer; $d * $b } << 1); ($d << 1) + do { use integer; $e / $b } } use Devel::Peek; Dump udiv64(10_000_000_000_000_000_011, 10); Dump udiv64(10_000_000_000_000_000_011, 1)

Replies are listed 'Best First'.
Re^2: 64-bit division anomolies (Solved.)
by BrowserUk (Patriarch) on Feb 17, 2015 at 12:44 UTC

    Neat. Thankyou.

    However, despite my initial misgivings of using a Math::* module with an overload interface -- mostly based on my bad experiences with using Math::BigInt way back when -- I was pleasantly surprised to discover that modifying the routine where the problem occurred from:

    sub Q2b36 { my $n = shift; ...

    to:

    sub Q2b36 { my $n = uint64( shift ); ...

    Fixed all the problems with no other changes required. About as simple as a work around for Perl's deficiencies could get.

    Once again. Thank you for Math::Int64 & Math::Int128.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked
Re^2: 64-bit division anomolies (Solved.)
by Discipulus (Canon) on Feb 17, 2015 at 09:42 UTC
    oh.. well.. If you have time, can i ask you to comment a bit more your code?
    just to make it more appreciable by people with low mathfu as me.. ;=)?

    L*
    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.
      My method, first builds an approximation of the solution of a/b as...
      s1 = ((a / 2) / b) * 2;
      a / 2 is done using the bug-free shift-right operator (>>) and results always in a number with bit 64 unset, so we can divide it by b without incurring in the convert-to-NV bug. Again multiplying by 2 is done with the shift-left operator (<<).

      Then, we use the approximation to build the exact solution as:

      s = s1 + (a - s1 * b) / b

      Well, actually, in order to do everything using bug-free operations, the code uses the following equivalence:

      s2 = (a / 2) / b s1 = s2 * 2 s = s1 + (a - s1 * b) / b s = s2 * 2 + (a - (s2 * b) * 2) / b
      where $d is s2, and $e is (a - (s2 * b) * 2).