Page 1 of 1

TzMemTable - Float field

Posted: 14.11.2021, 17:50
by kjteng
The following picuture shows a dbgrid which gets its data from a TZMemTable.
Some numbers are displayed as what I keyed in (eg. 1234.0, 1234.2, 1234.3) but some number are displayed with many decimals.
Something to do with the setting for the memtable, or the dbgrid ? Any help?
(Certainly I can set the display format to show all figures in two decimals, but it would be quite troublesome)
Screenshot (69).png

Re: TzMemTable - Float field

Posted: 14.11.2021, 18:06
by marsupilami
Hello kjteng,

this has to do with the semantics of a Float. Not all decimal numbers can be encoded as a float without requiring small alterations. This leads to the problem you see. The very same should happen on regular data fields.
If you need to store decimal plaxes in exactly the same way as they are entered, please use TBCDField or TFMTBCDField.

Best regards,

Jan

Re: TzMemTable - Float field

Posted: 14.11.2021, 20:02
by miab3
Hi kjteng,

This way you can force formatting:

Code: Select all

procedure TForm1.Button5Click(Sender: TObject);
var i:Integer;
begin
   with ZMemTable1 do
   for i := 0 to FieldCount-1 do
   begin
     case Fields[i].DataType of
      ftFloat, ftBCD:
        TNumericField(Fields[i]).DisplayFormat := '0.000';
      ftCurrency:
        TNumericField(Fields[i]).DisplayFormat := '0.00';
     end;
  end;
end; 
Michał

Re: TzMemTable - Float field

Posted: 15.11.2021, 06:32
by kjteng
marsupilami wrote: 14.11.2021, 18:06 Hello kjteng,

this has to do with the semantics of a Float. Not all decimal numbers can be encoded as a float without requiring small alterations. This leads to the problem you see. The very same should happen on regular data fields.
If you need to store decimal plaxes in exactly the same way as they are entered, please use TBCDField or TFMTBCDField.

Best regards,

Jan
Yes I understand that this is the nature of float data.
However, I still think it would be better if we can display the number in a more 'pleasant' way. For example Tmemdataset actually display the number based on 8 significant digits by default (which can be change) so that the numbers displayed will be the same as what the user keyed in. RXMemorydata also display the float based on precision (default is 0). May be you can consider: (i) to set default precision and (ii) to save the precision in SaveToStream. I have just created a helper file for my version of savetostream/loadfromstram (with the precision info). It seems to work.
I will post it for sharing/discussion later after more testing is done.

Re: TzMemTable - Float field

Posted: 15.11.2021, 06:40
by kjteng
miab3 wrote: 14.11.2021, 20:02 Hi kjteng,

This way you can force formatting:

Code: Select all

procedure TForm1.Button5Click(Sender: TObject);
var i:Integer;
begin
   with ZMemTable1 do
   for i := 0 to FieldCount-1 do
   begin
     case Fields[i].DataType of
      ftFloat, ftBCD:
        TNumericField(Fields[i]).DisplayFormat := '0.000';
      ftCurrency:
        TNumericField(Fields[i]).DisplayFormat := '0.00';
     end;
  end;
end; 
Michał
Yeah. As mentioned in my post earlier, I was doing it this way. However, I later I discovered that in some cases setting the precision property may be more appropriate (because the users want to see what exactly they have keyed in, i.e. 1.23 and 1.2300 has different meaning to them)

Re: TzMemTable - Float field

Posted: 15.11.2021, 20:54
by marsupilami
Hello kjteng,
kjteng wrote: 15.11.2021, 06:32 Yes I understand that this is the nature of float data.
However, I still think it would be better if we can display the number in a more 'pleasant' way. For example Tmemdataset actually display the number based on 8 significant digits by default (which can be change) so that the numbers displayed will be the same as what the user keyed in. RXMemorydata also display the float based on precision (default is 0). May be you can consider: (i) to set default precision and (ii) to save the precision in SaveToStream. I have just created a helper file for my version of savetostream/loadfromstram (with the precision info). It seems to work.
I will post it for sharing/discussion later after more testing is done.
I have to disagree about setting the default value of T(Z)FloatField.Precision. This is what I found on Embarcaderos Help on TFloatField.Precision:
Embarcadero online help on Data.DB.TFloatField.Precision wrote:The default value of Precision is 15 decimal places.
I see no reason to do it different because this way the user gets to see the full numer that is stored. If a user needs less significant places, it is the users responsibility to change this value.

But I agree that LoadFromStream and SaveToStream should save the properties of the fields, if possible.

Best regards,

Jan

Re: TzMemTable - Float field

Posted: 16.11.2021, 02:07
by kjteng
Hi Marsupilami,

I tried the following code (to set precision when I create a table) but failed (it always return -1, same code works for TMemDataSet).
with zmemtable1 do
begin
Close;
FieldDefs.Clear;
FieldDefs.Add('aa', ftFloat, 0, True);
FieldDefs.Items[0].Precision:= 12;
Open;
showmessage(IntToStr(TFloatField(Fieldbyname('aa')).Precision))
end;

Do I missed out anything? (BTW setting TFloatField(Fieldbyname('AAA')).precision := 12 after opening the zmemtable seems to work)