View Issue Details

IDProjectCategoryView StatusLast Update
0038631FPCRTLpublic2021-04-23 07:47
ReporterLagunov Aleksey Assigned ToFlorian  
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version3.3.1 
Summary0038631: function trunc not work correct
Descriptioncode:
var
  a:comp;
begin
  a:=123.123;
  writeln('a=',a:10:3, ' trunc(a)=', trunc(a));
  
  a:=123.523;
  writeln('a=',a:10:3, ' trunc(a)=', trunc(a));
end.

output:
 ./aa
a= 123.000 trunc(a)=123
a= 124.000 trunc(a)=124
TagsNo tags attached.
Fixed in Revision49247
FPCOldBugId
FPCTarget-
Attached Files

Activities

runewalsh

2021-03-16 16:40

reporter   ~0129713

Last edited: 2021-03-16 17:58

View 3 revisions

IIRC Comp is an integer, so '123.523' gets rounded to 124 already at the time of the assignment. Try to write it without 'trunc'.

Bart Broersma

2021-03-16 17:44

reporter   ~0129717

Delphi 7 has the exact same output.

Sven Barth

2021-03-16 20:39

manager   ~0129721

runewalsh is right. Your output after you assign to a the second time shows the value as is as well and that is already 124, nothing to truncate there.

Lagunov Aleksey

2021-03-17 06:43

reporter   ~0129726

Okay.
I made a wrong example. I was confused by the fact that the type cschz is declared as real in the documentation.
A rounding error occurs when dividing - here's an example.

const
  F = 10;
var
  A:comp;
  B: Extended;
  C1, C2:Integer;
begin
  A:=27;
  C1:=Trunc(A / F);

  B:=27;
  C2:=Trunc(B / F);
  writeln('C1=',C1, ' C2=', C2);
end.

There is a similar call in the rtl function MSecsToTimeStamp from sysutils - and this is a problem.

Lagunov Aleksey

2021-03-17 06:47

reporter   ~0129727

demo for MSecsToTimeStamp error.
msec_test1.lpr (786 bytes)   
program msec_test1;
uses sysutils;

function MSecsToTimeStamp1(MSecs: comp): TTimeStamp;
var
  D1:Int64;
begin
  D1:=Trunc(msecs);
  result.Date := D1 div msecsperday;
  result.Time := D1 - result.date * msecsperday;
end ;

var
  D: TDateTime;
  T, T1, T2: TTimeStamp;
  MS: Comp;
begin
  D:=EncodeDate(2021, 03, 16) + EncodeTime(14, 02, 15, 1);
  WriteLn('DATE: ', DateTimeToStr(D));

  T:=DateTimeToTimeStamp(D);
  WriteLn(' T.Date=',T.Date,'   T.Time=', T.Time);
  MS:=TimeStampToMSecs(T);
  T1:=MSecsToTimeStamp(MS);
  WriteLn('T1.Date=',T1.Date,'  T1.Time=', T1.Time);
  WriteLn('DATE1: ', DateTimeToStr(TimeStampToDateTime(T1)));
  T2:=MSecsToTimeStamp1(MS);
  WriteLn('T2.Date=',T2.Date,'  T2.Time=', T2.Time);
  WriteLn('DATE2: ', DateTimeToStr(TimeStampToDateTime(T2)));
end.

msec_test1.lpr (786 bytes)   

Bart Broersma

2021-03-17 11:38

reporter   ~0129738

It's a regression.

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas
Free Pascal Compiler version 3.3.1 [2021/03/14] for i386
Copyright (c) 1993-2021 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling test.pas
Linking test.exe
15 lines compiled, 0.1 sec, 30016 bytes code, 1332 bytes data

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
C1=3 C2=2

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>fpc test.pas
Free Pascal Compiler version 3.2.0 [2020/06/04] for i386
Copyright (c) 1993-2020 by Florian Klaempfl and others
Target OS: Win32 for i386
Compiling test.pas
Linking test.exe
15 lines compiled, 0.0 sec, 28096 bytes code, 1300 bytes data

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
C1=2 C2=2

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>dcc32 test.pas
Borland Delphi Version 15.0
Copyright (c) 1983,2002 Borland Software Corporation
test.pas(16)
17 lines, 0.02 seconds, 10840 bytes code, 1821 bytes data.

C:\Users\Bart\LazarusProjecten\ConsoleProjecten>test
C1=2 C2=2

Florian

2021-03-17 21:21

administrator   ~0129747

This is probably due to my excessprecision changes. The question however is, to what type comp / integer should be converted. I consider the choice of 3.2.0 of using extended as rather random, in particular as other platforms support only double and then comp / integer using double to do the division causes rounding errors as well for large comp values. I consider it more consistent to evaluate comp / integer using comp. comp being just a fixed point type without fractional part.

BTW: Compiling with -Sd should give the same result as in delphi.

Sergey S.

2021-04-09 05:32

reporter   ~0130188

"There is a similar call in the rtl function MSecsToTimeStamp from sysutils - and this is a problem." I confirm that there is a problem.
I am using the version of the "MSecsToTimeStamp" function proposed by Lagunov Aleksey

Marco van de Voort

2021-04-17 15:43

manager   ~0130428

I wonder why those functions use COMP at all, and not int64 ?

Florian

2021-04-18 11:23

administrator   ~0130438

Maybe ancient code from times when int64 was not available?

Florian

2021-04-22 22:16

administrator   ~0130529

Thanks, I added your fixed MSecsToTimeStamp function to sysutils.

While the initial behaviour was fine for CPUs having an extended type, converting comp to double when doing a <comp> / integer division on CPUs with only a double type is wrong as it results in precision loss.

Lagunov Aleksey

2021-04-23 07:47

reporter   ~0130534

thanks. fixed.

Issue History

Date Modified Username Field Change
2021-03-16 14:16 Lagunov Aleksey New Issue
2021-03-16 16:40 runewalsh Note Added: 0129713
2021-03-16 16:41 runewalsh Note Edited: 0129713 View Revisions
2021-03-16 17:44 Bart Broersma Note Added: 0129717
2021-03-16 17:58 runewalsh Note Edited: 0129713 View Revisions
2021-03-16 20:39 Sven Barth Assigned To => Sven Barth
2021-03-16 20:39 Sven Barth Status new => resolved
2021-03-16 20:39 Sven Barth Resolution open => no change required
2021-03-16 20:39 Sven Barth FPCTarget => -
2021-03-16 20:39 Sven Barth Note Added: 0129721
2021-03-17 06:43 Lagunov Aleksey Status resolved => feedback
2021-03-17 06:43 Lagunov Aleksey Resolution no change required => open
2021-03-17 06:43 Lagunov Aleksey Note Added: 0129726
2021-03-17 06:47 Lagunov Aleksey Note Added: 0129727
2021-03-17 06:47 Lagunov Aleksey File Added: msec_test1.lpr
2021-03-17 06:47 Lagunov Aleksey Status feedback => assigned
2021-03-17 11:38 Bart Broersma Note Added: 0129738
2021-03-17 21:21 Florian Note Added: 0129747
2021-04-09 05:32 Sergey S. Note Added: 0130188
2021-04-17 15:43 Marco van de Voort Note Added: 0130428
2021-04-18 11:23 Florian Note Added: 0130438
2021-04-18 13:35 Sven Barth Assigned To Sven Barth =>
2021-04-18 13:36 Sven Barth Status assigned => new
2021-04-22 22:16 Florian Assigned To => Florian
2021-04-22 22:16 Florian Status new => resolved
2021-04-22 22:16 Florian Resolution open => fixed
2021-04-22 22:16 Florian Fixed in Revision => 49247
2021-04-22 22:16 Florian Note Added: 0130529
2021-04-23 07:47 Lagunov Aleksey Status resolved => closed
2021-04-23 07:47 Lagunov Aleksey Note Added: 0130534