New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
64-bit Integers -- inexact division gives odd result when is large #9316
Comments
From chris.hall@highwayman.comCreated by chris.hall@highwayman.comDivision of a large 64-bit integer by a small integer gives peculiar Consider: idiv(0x0FED_CBA9_8765_4321, 9, 9) ; print "_" x 70, "\n" ; idiv(1<<52, 3, 2) ; sub idiv { printf "a = 0x%016X * $b + i, for i = 0..%d\n", $z, $j ; foreach my $i (0..$j) { printf " %2d: 0x%016X : %20s : %+3d : %+5d\n", $i, $d, "$q", $r, $s ; which on an x86-64 produces: a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9 The first section shows the effect. Where the integer division is exact we I assume that the code runs an integer division, and when the remainder is The second section shows what happens when the result of the division is I suggest that the code should be extended to check if the result is
(As shown above, the % operator is giving the right result. So all is [FWIW: Round-to-Even is all very well, but in this case truncation would Perl Info
|
From shouldbedomo@mac.comOn 2008–05–06, at 19:58, Chris Hall (via RT) wrote: Good news -- from the point of view of repeatability: I get the same
Bad news from the point of view of understanding the phenomenon: I get These modules appear to be behaving themselves: domo:64-bit_perl-current$ ./perl -lwe '$x=2**60 + 3; print $x/2 - 2**59' Can you say why I should be getting the same results from your test |
The RT System itself - Status changed from 'new' to 'open' |
From chris.hall@highwayman.comOn Wed, 7 May 2008 you wrote
Documentation says that 2**n is a floating value. So you'll find that: $ perl -lwe '$x=2**63 + 27; print $x - 2**63' More interesting is: $ perl -lwe '$x=(1<<62) + 27; print $x - (1<<62)' $ perl -lwe '$x=(1<<62) + 27; print $x/2 - (1<<61)' but when the division is exact: $ perl -lwe '$x=(1<<62) + 26; print $x/2 - (1<<61)' When $x = 2**62 + 27, $x/2 is 2**61 + 13.5 -- forcing that to floating
umm... this is different from the result when $x/2 is pushed into With -Minteger 2**n is clearly an integer: $ perl -Ilib -Minteger -lwe '$x=(2**62) + 27; print $x - (2**62)' And, since division now truncates: $ perl -Ilib -Minteger -lwe '$x=(2**62) + 27; print $x/2 - (2**61)'
Similarly: $ perl -Ilib -Mbigint -lwe '$x=(2**62) + 27; print $x/2 - (2**61)' Is the same as -Minteger, but different from the default case.
Not really. If I run my test with -Minteger, I get: a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9 which is what you'd expect for truncating integer division... ...and not the same as the default case, where the division is rounded a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9 Are you getting something else ? Chris |
From @dcollinsnI have attempted to reproduce the original testcase, and 64-bit-all builds of both 5.20.0 and blead behave properly: a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9 Unless anyone has a different understanding of this issue, we should write a test case and close this bug. |
From [Unknown Contact. See original ticket]I have attempted to reproduce the original testcase, and 64-bit-all builds of both 5.20.0 and blead behave properly: a = 0x0FEDCBA987654321 * 9 + i, for i = 0..9 Unless anyone has a different understanding of this issue, we should write a test case and close this bug. |
From @dcollinsnmea culpa - This (and #62746) still fail in blead with -Duse64bitall On Tue, Jun 7, 2016 at 8:08 PM, Dan Collins via RT <perlbug-comment@perl.org
|
Long double means different things on different platforms. On many (e.g. Mac M1) it is equal to double, so we will see the same behavior. On some x86-64 hardware + compilers, it is extended. On others, or with quadmath, it is greatly extended. 'use integer' has other issues:
Neither of which are correct. The first because the division is done as FP then converted back to an integer with loss of precision. The second because 'use integer' cast the first number into an IV. On an x86-64 with long double (nvsize=16), the first result does turn out correct, as does a quadmath build (__float128). But the same machine without long double or quadmath gives the incorrect result. My M1 Mac, built with long double, also gives the incorrect result, as expected since that hardware/compiler treats long double = double. I'm not sure if this is directly applicable to the OP's issue, but maybe sheds some light on the tests. A solution for correct integer division is either using a module or adding a new operator for correct 64-bit integer floored division (e.g. Raku's div and mod, or Pari/GP's '', or Python's '//'). This would also have the benefit of being more consistent with the existing floored mod operator. This seems highly unlikely to happen. |
Seems that perl resorts to FP division of integers only if the exact result of the division is not an integer.
Admittedly, that's not as convenient as having actual operators that will return the desired results but, apart from that, is there any deficiency with it ? |
I wish that was true, but there are exceptions. E.g. Perl 5.32.1 and 5.33.7 give me:
Argh. If it worked, we could make your divmod function give the truncated quotient and remainder, like C99, for both positive and negative numbers, using one (ugly) extra line of code, e.g.:
It works for most inputs, but there is a range that results in bad results. |
Yes - I misread the behaviour, and on a perl whose nvsize is 8 it's not going to work if the division results in a value that cannot be represented exactly in 53 (or fewer) bits. For perls whose nvsize and ivsize are both 8, I think you'll have to resort to XS or Inline::C. Math::Int64 might already provide just what's needed, but I haven't checked on that. |
Migrated from rt.perl.org#53784 (status was 'open')
Searchable as RT53784$
The text was updated successfully, but these errors were encountered: