Problem with FLOAT64 arithmetic
The problem can be reproduced with the following code (please pay attention to the comments):
MODULE TestFloat64;
IMPORT
Commands;
PROCEDURE Test*(ctx: Commands.Context);
VAR
days, hours, minutes, seconds: SIGNED32;
timei: SIGNED64;
time0, time1, time2, time3: FLOAT64;
PROCEDURE Check(condition: BOOLEAN);
BEGIN
ASSERT(condition);
FINALLY
END Check;
BEGIN
days := 43403; hours := 15; minutes := 35; seconds := 55;
timei := SIGNED64(days)*86400 + SIGNED64(hours)*3600 + SIGNED64(minutes)*60 + SIGNED64(seconds);
time0 := timei;
time1 := FLOAT64(days)*86400.0D0 + FLOAT64(hours)*3600.0D0 + FLOAT64(minutes)*60.0D0 + FLOAT64(seconds);
time2 := FLOAT64(days)*86400 + FLOAT64(hours)*3600 + FLOAT64(minutes)*60 + FLOAT64(seconds);
time3 := days*86400.0D0 + hours*3600.0D0 + minutes*60.0D0 + seconds;
TRACE(timei);
TRACE(time0, time1, time2, time3);
ctx.out.String("timei="); ctx.out.Int(timei, 0); ctx.out.Ln;
ctx.out.String("time0="); ctx.out.FloatFix(time0, 0, 15, 0); ctx.out.Ln;
ctx.out.String("time1="); ctx.out.FloatFix(time1, 0, 15, 0); ctx.out.Ln;
ctx.out.String("time2="); ctx.out.FloatFix(time2, 0, 15, 0); ctx.out.Ln;
ctx.out.String("time3="); ctx.out.FloatFix(time3, 0, 15, 0); ctx.out.Ln;
ctx.out.Update;
Check(timei = 3750075355); (*OK*)
Check(time0 = 3750075355); (*OK*)
Check(time1 = 3750075355); (*!FAILS (least significant bit of mantissa is 1 instead of 0)*)
Check(time2 = 3750075355); (*OK*)
Check(time3 = 3750075355); (*!FAILS (completely wrong result)*)
END Test;
END TestFloat64.
(from redmine: issue id 95, created on 2020-01-15 by root)