[bug_report] FIREBIRD and NUMERIC/DECIMAL
Moderators: EgonHugeist, mdaems
[bug_report] FIREBIRD and NUMERIC/DECIMAL
Hi,
Could you please help me. I am using Delphi 6 / Zeos 6.5.1 / Firebird 1.5
CREATE TABLE xxx (
...
CENA NUMERIC(5, 2 NOT NULL,
CENADPH NUMERIC(5, 2) NOT NULL
...
);
OK
INSERT INTO xxx VALUES (... , 415.80, 625.90, ...);
OK
SELECT * FROM xxx;
DBGrid show :
CENA = 415.8000015654
CENADPH = 625.9000154654
with IBDatabase component
DBGrid show
CENA = 415.8
CENADPH = 625.9
OK
Thanks very much
Could you please help me. I am using Delphi 6 / Zeos 6.5.1 / Firebird 1.5
CREATE TABLE xxx (
...
CENA NUMERIC(5, 2 NOT NULL,
CENADPH NUMERIC(5, 2) NOT NULL
...
);
OK
INSERT INTO xxx VALUES (... , 415.80, 625.90, ...);
OK
SELECT * FROM xxx;
DBGrid show :
CENA = 415.8000015654
CENADPH = 625.9000154654
with IBDatabase component
DBGrid show
CENA = 415.8
CENADPH = 625.9
OK
Thanks very much
The situacion is the TYPE of variable or FieldType that is being generated, which is a TFloatField. This is NORMAL behaviour for most data access components.
The fix being mentioned in this thread is ONLY functional for displaying purposes, e.g. display the value correctly, but internally, the value is still 415.8000015654 instead of 415.80 for use in calculations. If the the program reads many records and summing a total with these values, there will can diferences in the results.
This is a problem that has ALLWAYS existed in computers since the first computer ever invented (1950's).
The only REAL solution is to be able to OPTIONALLY specify in ZEOS to create TBCDField or TFmtBCDField types (which are more precise but slower) instead of TFloatField in case of NUMERIC or DECIMAL database field types.
The TFloatField type is equivalent to a "double" type variable and a TBCDField is equivalent to a "currency" type variable. In the help files you should be able to investigate the diferences between these types of variables.
Maybe next week I may be able to look into the sources and determine exactly what changes are necessary to be able to make this option available to developers. However, no matter what changes can be made to ZeosLib, the default behaviour still has to be same (Create TFloatField types) and be only overriden by a property specifying the Numeric Type desired.
Regards
Jose Ostos
The fix being mentioned in this thread is ONLY functional for displaying purposes, e.g. display the value correctly, but internally, the value is still 415.8000015654 instead of 415.80 for use in calculations. If the the program reads many records and summing a total with these values, there will can diferences in the results.
This is a problem that has ALLWAYS existed in computers since the first computer ever invented (1950's).
The only REAL solution is to be able to OPTIONALLY specify in ZEOS to create TBCDField or TFmtBCDField types (which are more precise but slower) instead of TFloatField in case of NUMERIC or DECIMAL database field types.
The TFloatField type is equivalent to a "double" type variable and a TBCDField is equivalent to a "currency" type variable. In the help files you should be able to investigate the diferences between these types of variables.
Maybe next week I may be able to look into the sources and determine exactly what changes are necessary to be able to make this option available to developers. However, no matter what changes can be made to ZeosLib, the default behaviour still has to be same (Create TFloatField types) and be only overriden by a property specifying the Numeric Type desired.
Regards
Jose Ostos
I have looked deep into the sources and have not quite found exactly where the problem is, but it does appear to be a small bug in the interbase/firebird driver.
background: Decimal types are stored internally as some variation of an integer type depending on the precision and scale of the decimal. In the given example "DECIMAL(5,2)" it uses an integer (4 bytes) but a "DECIMAL(13,2" uses a Int64 (8 bytes).
I made tests with variables with both these diferent types and only the "DECIMAL(5,2)" produces this situation. In other words, the problem is only with decimals that are stored as a (4 byte) integer.
I have already spend about 16 hours with this without success. This requires someone with a lot of knowledge of the internal workings of the interbase/firebird driver to determine exactly at what point the data is converted from the record buffer to the actual field values and how this conversion is being done which is what needs to be fixed.
Sorry I could not be of more help or maybe someone can orient me in the right direction.
Regards
Jose Ostos
background: Decimal types are stored internally as some variation of an integer type depending on the precision and scale of the decimal. In the given example "DECIMAL(5,2)" it uses an integer (4 bytes) but a "DECIMAL(13,2" uses a Int64 (8 bytes).
I made tests with variables with both these diferent types and only the "DECIMAL(5,2)" produces this situation. In other words, the problem is only with decimals that are stored as a (4 byte) integer.
I have already spend about 16 hours with this without success. This requires someone with a lot of knowledge of the internal workings of the interbase/firebird driver to determine exactly at what point the data is converted from the record buffer to the actual field values and how this conversion is being done which is what needs to be fixed.
Sorry I could not be of more help or maybe someone can orient me in the right direction.
Regards
Jose Ostos