View Issue Details

ID Project Category View Status Date Submitted Last Update 0033167 FPC RTL public 2018-02-13 19:30 2019-12-09 13:09 wp normal minor have not tried new reopened 3.1.1 3.1.1 0033167: Calculation errors of floating point "mod" operation The unit math of fpc-trunk implements the "mod" operator for floating point numbers. This is coded as   operator mod(const a,b:float) c:float;inline;   begin     c:= a-b * Int(a/b);   end; However, since the integer part of ratio a/b may be off by 1 the result can be off by one divisor if the result is expected to be close to 0. Example:   a = 7.7   b = 1.1 Simple math tells that a mod b should be 0 here because 7.7/1.1 = 7.0. But due to the finite precision of floating point values the ratio actually turns out to be 6.9999999. Together with the Int() operation the result of the mod operation is off by 1 divisor. However, since the remainder of a division is always less than the divisor this error case can be detected by checking c and b for equality with the function SameValue which takes machine precision into account. Furthermore, the function abs should be used to cover the case of negative values.   operator mod(const a,b:float) c:float;inline;   begin     c:= a-b * Int(a/b);     if SameValue(abs(c), abs(b)) then c := 0.0;   end; Run this project: program Project1; uses   Math; operator mod(const a,b:Double) c:Double; inline; begin   c:= a-b * Int(a/b);   //if SameValue(abs(c), abs(b)) then c := 0; // Uncomment to see effect of fix end; procedure Test(Dividend, Divisor: double); var   res: Double; begin   WriteLn('Dividend: ', Dividend:10:5);   WriteLn('Divisor : ', Divisor:10:5);   WriteLn('Dividend/Divisor = ', Dividend/Divisor);   res := Dividend mod Divisor;   WriteLn('Result: ', res:10:5);   WriteLn; end; begin   Test(7.7, 1.1);   Test(-7.7, 1.1);   Test(7.7, -1.1);   Test(-7.7, -1.1);   {   Test(7.2, 1.1);   Test(7.2, -1.1);   Test(-7.2, 1.1);   Test(-7.2, -1.1);   }   ReadLn; end. I am not sure if negative values are handled by the fpc code correctly, anyway. I compared with Wolfram Alpha output:  7.2 mod 1.1 = 0.6 (Wolfram Alpha), same here  7.2 mod -1.1 = -0.5 (Wolfram Alpha), but 0.6 here  -7.2 mod 1.1 = 0.5 (Wolfram Alpha), but -0.6 here  -7.2 mod -1.1 = -0.6 (Wolfram Alpha), same here To me it looks as if there is no clear definition how to handle negative values: https://en.wikipedia.org/wiki/Modulo_operation No tags attached. 38332 Attached Files

Issue History

2018-02-13 19:30 wp New Issue
2018-02-13 19:51 wp Note Added: 0106373
2018-02-13 20:00 wp Note Edited: 0106373 View Revisions
2018-02-13 22:00 Florian Note Added: 0106374
2018-02-13 22:38 Martok Note Added: 0106376
2018-02-13 23:19 Florian Note Added: 0106377
2018-02-14 08:32 Martok Note Added: 0106383
2018-02-14 08:38 Thaddy de Koning Note Edited: 0106384 View Revisions
2018-02-14 09:07 wp Note Added: 0106385
2018-02-24 19:23 Florian Fixed in Revision => 38332
2018-02-24 19:23 Florian Note Added: 0106591
2018-02-24 19:23 Florian Status new => resolved
2018-02-24 19:23 Florian Fixed in Version => 3.1.1
2018-02-24 19:23 Florian Resolution open => fixed
2018-02-24 19:23 Florian Assigned To => Florian
2018-02-26 01:14 wp Note Added: 0106635
2018-02-26 01:14 wp Status resolved => feedback
2018-02-26 01:14 wp Resolution fixed => reopened
2018-02-26 03:40 jamie philbrook Note Added: 0106636
2018-02-26 03:43 jamie philbrook Note Edited: 0106636 View Revisions
2018-02-26 07:50 Thaddy de Koning Note Edited: 0106637 View Revisions
2018-02-26 07:55 Thaddy de Koning Note Edited: 0106637 View Revisions
2018-02-26 08:00 Thaddy de Koning Note Edited: 0106637 View Revisions
2018-02-26 08:16 Thaddy de Koning Note Edited: 0106638 View Revisions
2018-02-26 10:28 delfion Note Added: 0106642
2018-03-14 21:43 Florian Note Added: 0107114
2018-03-14 21:44 Florian File Added: tw33167.pp
2018-03-14 21:44 Florian Assigned To Florian =>