View Issue Details

IDProjectCategoryView StatusLast Update
0035374LazarusTAChartpublic2019-04-14 01:47
ReporterMarcin WiazowskiAssigned Towp 
PrioritynormalSeverityminorReproducibilityalways
Status closedResolutionfixed 
Product Version2.1 (SVN)Product Build60960 
Target Version2.2Fixed in Version 
Summary0035374: TAChart: some data formatting issue in TListChartSource
DescriptionThere is some issue with converting data points to LFM stream in TListChartSource.

Let's load the attached Reproduce application in IDE - it contains RandomChartSource1 and ListChartSource1 on the form. Now:
- select RandomChartSource1 and set XMax to 0.3,
- select ListChartSource1, launch DataPoints editor and set X value to 0.3.

Now save the project and look into the LFM file:
- both XMax and X values are declared as Double in source files,
- both have been set to 0.3
- but, in the LFM file, we have:

  object RandomChartSource1: TRandomChartSource
    ...
    XMax = 0.3
    ...
  end
  object ListChartSource1: TListChartSource
    DataPoints.Strings = (
      '0.29999999999999999||?|'
    ...
  end

So the same entered value - i.e. 0.3 - was saved as:
- '0.3' string, when conversion has been performed by IDE itself,
- '0.29999999999999999' string, when conversion has been performed by TListChartSource.

If we now open DataPoints editor, we can see '0.29999999999999999' there, which is quite ugly...



Short investigation shows, that IDE - when converting Double values to LFM stream (i.e. to string) - uses LResources.pp unit -> LRSObjectBinaryToText() -> ProcessValue(), where the following code is called:

  vaExtended: begin
    ext:=ReadLRSExtended(Input);
    OutLn(FloatToStr(ext));
  end;

So, to convert floating point variable to string, simple FloatToStr() call is made (however, default format settings are prepared earlier).



On the contrary, TListChartSource calls its TListChartSourceStrings.Get() -> NumberStr(), where we can find:

  function NumberStr(AValue: Double): String;
  begin
    if IsNaN(AValue) then
      Result := '|'
    else
      Result := Format('%g|', [AValue], DefSeparatorSettings);
  end;

So, in this case, Format('%g') is called. This explains the difference between IDE and TListChartSource.



Now some interesting observation: both '0.3' and '0.29999999999999999' strings map to the same Double value:

  procedure TForm1.Button1Click(Sender: TObject);
  var
    D1, D2: Double;
  begin
    D1 := StrToFloat('0.3');
    D2 := StrToFloat('0.29999999999999999');
    if D1 = D2 then
      Caption := 'equal'
    else
      Caption := 'NOT equal';
  end;

This is due to limited floating point precision. So it's better to write just '0.3' to the stream also in TListChartSource's case - which will be both coherent with IDE and also what the user entered. And the precision will not be altered. The attached patch implements this.
TagsNo tags attached.
Fixed in Revision60961
LazTarget2.2
WidgetsetWin32/Win64
Attached Files
  • Reproduce.zip (1,929 bytes)
  • patch.diff (517 bytes)
    Index: components/tachart/tasources.pas
    ===================================================================
    --- components/tachart/tasources.pas	(revision 60960)
    +++ components/tachart/tasources.pas	(working copy)
    @@ -319,7 +319,8 @@
         if IsNaN(AValue) then
           Result := '|'
         else
    -      Result := Format('%g|', [AValue], DefSeparatorSettings);
    +      // call FloatToStr() to make the conversion exactly same as IDE does
    +      Result := FloatToStr(AValue, DefSeparatorSettings) + '|';
       end;
     
     var
    
    patch.diff (517 bytes)

Activities

Marcin Wiazowski

2019-04-13 19:51

reporter  

Reproduce.zip (1,929 bytes)

Marcin Wiazowski

2019-04-13 19:51

reporter  

patch.diff (517 bytes)
Index: components/tachart/tasources.pas
===================================================================
--- components/tachart/tasources.pas	(revision 60960)
+++ components/tachart/tasources.pas	(working copy)
@@ -319,7 +319,8 @@
     if IsNaN(AValue) then
       Result := '|'
     else
-      Result := Format('%g|', [AValue], DefSeparatorSettings);
+      // call FloatToStr() to make the conversion exactly same as IDE does
+      Result := FloatToStr(AValue, DefSeparatorSettings) + '|';
   end;
 
 var
patch.diff (517 bytes)

wp

2019-04-14 00:07

developer   ~0115483

Thank you - this fixes one of the major annoyances with the datapoint editor.

Marcin Wiazowski

2019-04-14 01:47

reporter   ~0115485

Fixed, thanks!

Issue History

Date Modified Username Field Change
2019-04-13 19:51 Marcin Wiazowski New Issue
2019-04-13 19:51 Marcin Wiazowski File Added: Reproduce.zip
2019-04-13 19:51 Marcin Wiazowski File Added: patch.diff
2019-04-14 00:07 wp Fixed in Revision => 60961
2019-04-14 00:07 wp LazTarget => 2.2
2019-04-14 00:07 wp Note Added: 0115483
2019-04-14 00:07 wp Status new => resolved
2019-04-14 00:07 wp Resolution open => fixed
2019-04-14 00:07 wp Assigned To => wp
2019-04-14 00:07 wp Target Version => 2.2
2019-04-14 01:47 Marcin Wiazowski Note Added: 0115485
2019-04-14 01:47 Marcin Wiazowski Status resolved => closed