perlquestion syphilis Hi,<br><br> <b>UPDATE:</b> I've now filed a [https://github.com/Perl/perl5/issues/18889|bug report] about this. <br><br>I've been chewing on this over the last couple of days, and it doesn't look right to me. <br>It's an issue that arises only when NV-precision is greater than IV-precision. <br>So, if ivsize is 8 bytes, then in order to experience the issue, you'll generally need to use a quadmath build (nvtype of __float28, NV-precision of 113 bits). <br>With such a perl, I get: <c> C:\_32>perl -wle "\$m = (2**113) - 1; \$n = 2; print \$m % \$n;" 0 </c> In contrast, POSIX::fmod returns "1" for the same operation. <c> C:\_32>perl -MPOSIX -wle "\$m = (2**113) - 1; \$n = 2; print fmod(\$m, \$n);" 1 </c> Here's the section of perlop documentation that I'm looking at: <c> Binary "%" is the modulo operator, which computes the division remainder of its first argument with respect to its second argument. Given integer operands \$m and \$n: If \$n is positive, then "\$m % \$n" is \$m minus the largest multiple of \$n less than or equal to \$m. If \$n is negative, then "\$m % \$n" is \$m minus the smallest multiple of \$n that is not less than \$m (that is, the result will be less than or equal to zero). If the operands \$m and \$n are floating point values and the absolute value of \$n (that is "abs(\$n)") is less than "(UV_MAX + 1)", only the integer portion of \$m and \$n will be used in the operation (Note: here "UV_MAX" means the maximum of the unsigned integer type). If the absolute value of the right operand ("abs(\$n)") is greater than or equal to "(UV_MAX + 1)", "%" computes the floating-point remainder \$r in the equation "(\$r = \$m - \$i*\$n)" where \$i is a certain integer that makes \$r have the same sign as the right operand \$n (not as the left operand \$m like C function "fmod()") and the absolute value less than that of \$n. Note that when "use integer" is in scope, "%" gives you direct access to the modulo operator as implemented by your C compiler. This operator is not as well defined for negative operands, but it will execute faster. </c> AFAICT, the parts of that documentation that are pertinent to my given example are: <c> If \$n is positive, then "\$m % \$n" is \$m minus the largest multiple of \$n less than or equal to \$m. .... If the operands \$m and \$n are floating point values and the absolute value of \$n (that is "abs(\$n)") is less than "(UV_MAX + 1)", only the integer portion of \$m and \$n will be used in the operation (Note: here "UV_MAX" means the maximum of the unsigned integer type) </c> And to me that implies that the correct calculation for the given example is to do: <c> C:\_32>perl -wle "\$r = 10384593717069655257060992658440191.0 - (5192296858534827628530496329220095.0 * 2); print \$r;" 1 </c> This agrees with the value produced by POSIX::fmod(), but disagrees with the value produced by the "%" operator. <br>Do we agree that perl is buggy here ? <br><br> If you have a perl with ivsize of 4, you can also demonstrate the same issue. <br>With ivsize of 4, NV-precision of 113 bits: <c> C:\_32>perl -wle "\$m = (2**113) - 1; \$n = 2; print \$m % \$n;" 0 C:\_32>perl -MPOSIX -wle "\$m = (2**113) - 1; \$n = 2; print fmod(\$m, \$n);" 1 </c> With ivsize of 4, NV-precision of 64 bits (long double): <c> C:\>perl -wle "\$m = (2**64) - 1; \$n = 2; print \$m % \$n;" 0 C:\>perl -MPOSIX -wle "\$m = (2**64) - 1; \$n = 2; print fmod(\$m, \$n);" 1 </c> And now to really muddy the waters !! One might be expecting the trend to continue when ivsize is 4, and NV-precision is 53-bits .... but not so: <c> C:\_32>perl -wle "\$m = (2**53) - 1; \$n = 2; print \$m % \$n;" 1 C:\_32>perl -MPOSIX -wle "\$m = (2**53) - 1; \$n = 2; print fmod(\$m, \$n);" 1 </c> This time the "%" operator decides to act in accordance with (my reading of) the perlop documentation. <br><br>Cheers,<br>Rob