TAChart: some data formatting issue in TListChartSource
Original Reporter info from Mantis: Marcin Wiazowski
-
Reporter name:
Original Reporter info from Mantis: Marcin Wiazowski
- Reporter name:
Description:
There 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.
Mantis conversion info:
- Mantis ID: 35374
- Build: 60960
- Version: 2.1 (SVN)
- Fixed in revision: 60961 (#a154d474)
- Target version: 2.2