Henry Olive 5 Posted April 8, 2023 Good Day, var a,b : Double a:= 66,3333 b:= 1,5 c:= a* b ( Delphi shows c:= 99,5, actually c should be 99,49995 ) How can i get exact result ( 99,49995 ) ? Thank You Share this post Link to post
PeterBelow 239 Posted April 8, 2023 How do you display the result? You can control the number of decimals displayed when converting a floating-point value from its internal binary (not decimal!) representation, but the exact syntax depends on the function you use (Write, WriteLn, Format, FormatFloat, FloatToStr, FloatToStrF etc. The run-time library has accumulated quite a number of such conversion functions over time. Oh, and the result of your multiplication is actually not exactly 99,49995 since the computer stores numbers as binary and not as decimal, and since it only has a limited number of bits available many decimal numbers cannot be stored without a small loss of precision. These errors accumulate over calculation steps... Share this post Link to post
Henry Olive 5 Posted April 8, 2023 Thank you so much Peter I dont convert anything My Code = a:= MyQuery.FieldByName('TOTAL').asFloat; (which is 66,3333.-) b:= MyQuery.FieldByName('RATIO').asFloat; (Which is 1,50 ); c:= a * b; // In Debug i see c as 99,50 instead of 99,4999 MyTable.Edit; MyTableBENF.asFloat := c; // i was expecting to see in mytable's BENF field 99,49 not 99,50 (BENF field in firebird3 database is as Numeric(15,2) (In Delphi my table's releated field's Currency proporties = True) Share this post Link to post
KodeZwerg 54 Posted April 8, 2023 var a, b, c: Double; begin try a := 66.3333; b := 1.5; c := a * b; WriteLn(FloatToStrF(c, ffFixed, 16, 5)); ReadLn; except on E: Exception do Writeln(E.ClassName, ': ', E.Message); end; end. Output: 99,49995 Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 (edited) Guys, I think the problem reported above is more related to the Database than to Delphi itself and its adventures! We must remember that the numbers, as reported above, are stored binary, not decimal! And, when you define a field of type NUMERIC/DECIMAL 15x2, then, we must remember the range of the smallest and largest value that can be stored in this field! For that, you can check the Database or Delphi documentation. See the example using Firebird 4.02, I created 6 fields: Quote CREATE TABLE MYTABLENUMERIC ( FNUMERIC15X2 NUMERIC(15,2), FNUMERIC15X3 NUMERIC(15,3), FDECIMAL15X2 DECIMAL(15,2), FDECIMAL15X3 DECIMAL(15,3), FNUMERIC15X5 NUMERIC(15,5), <------- try keep the "precision" FDECIMAL15X5 NUMERIC(15,5) <------- maybe not as you see on "precision storing" ); and using the formula from the first post, see the results: implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); begin FDQuery1.Open; end; procedure TForm1.Button2Click(Sender: TObject); var a, b, c: double; begin a := 66.3333; b := 1.5; c := a * b; Edit1.Text := c.ToString; // FDQuery1.Append; FDQuery1.Fields[0].AsFloat := c; FDQuery1.Fields[1].AsFloat := c; FDQuery1.Fields[2].AsFloat := c; FDQuery1.Fields[3].AsFloat := c; FDQuery1.Fields[4].AsFloat := c; FDQuery1.Fields[5].AsFloat := c; FDQuery1.Post; end; procedure TForm1.FormCreate(Sender: TObject); begin FDConnection1.Close; end; end. NOTE: Now, YOU can use "DisplayFormat" to show your value in another "MASK" for example: 0.##, ###,00 etc... but the "real value stored on database" is another of course! Edited April 8, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 (edited) Firebird/InterBase® converts the columns as follows: Definition Data type Created Decimal(1)-Decimal(4) Small Integer Decimal(5)-Decimal(9) Integer Decimal(10)-Decimal(18) Int (64) Note that if a DECIMAL(5) data type is specified, it is actually possible to store a value as high as a DECIMAL(9) because Firebird/InterBase® uses the smallest available data type to hold the value. For a DECIMAL(5) column, this is an INTEGER, which can hold a value as high as a DECIMAL(9). Enhancement in precision of calculations with NUMERIC/DECIMAL (Firebird 4.0) Supported in IBExpert since version 2017.12.03. Source: https://github.com/FirebirdSQL/firebird/blob/master/doc/sql.extensions/README.data_types Function Maximum precision of NUMERIC and DECIMAL data types is increased to 34 digits. Author Alex Peshkoff <peshkoff@mail.ru> Syntax rules NUMERIC ( P {, N} ) DECIMAL ( P {, N} ) where P is precision (P <= 34, was limited prior with 18 digits) and N is optional number of digits after decimal separator (as before). Storage 128-bit, format according to IEEE 754. Example(s) 1. DECLARE VARIABLE VAR1 DECIMAL(25); 2. CREATE TABLE TABLE1 (FIELD1 NUMERIC(34, 17)); Note(s) Numerics with precision less than 19 digits use SMALLINT, INTEGER, BIGINT or DOUBLE PRECISION as base datatype depending upon number of digits and dialect. When precision is between 19 and 34 digits DECFLOAT(34) is used for it. Actual precision is always increased to 34 digits. For complex calculations such digits are casted (internally, in trivial way) to DECFLOAT(34) and the result of various math (log, exp, etc.) and aggregate functions using high precision numeric argument is DECFLOAT(34). -------- more info in: https://www.ibexpert.net/ibe/pmwiki.php?n=Doc.DefinitionNUMERICDECIMAL Edited April 8, 2023 by programmerdelphi2k Share this post Link to post
David Heffernan 2353 Posted April 8, 2023 5 hours ago, Henry Olive said: var a,b : Double a:= 66,3333 b:= 1,5 c:= a* b What language is this? It's not Delphi. Also, your expectation is incorrect. This is what Python says the right answer is: >>> 66.3333 * 1.5 99.49994999999998 I expect that if you showed your actual code, it would be clear what is going on. Share this post Link to post
David Heffernan 2353 Posted April 8, 2023 21 minutes ago, programmerdelphi2k said: I think the problem reported above is more related to the Database Where in the question is a database mentioned? Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 (edited) Edited April 8, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 (edited) And for those who are "blind" due to constant and innate bad temper... FDQUERY ->> accesses a data source in a DATABASE! 3 hours ago, Henry Olive said: (BENF field in firebird3 database is as Numeric(15,2) 3 hours ago, Henry Olive said: My Code = a:= MyQuery.FieldByName('TOTAL').asFloat; (which is 66,3333.-) b:= MyQuery.FieldByName('RATIO').asFloat; (Which is 1,50 ); c:= a * b; // In Debug i see c as 99,50 instead of 99,4999 MyTable.Edit; Edited April 8, 2023 by programmerdelphi2k Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 Does Python have an RTL and Delphi Object PASCAL forum? the question remains Share this post Link to post
programmerdelphi2k 237 Posted April 8, 2023 to "force" usage +decimals you can try this: varX * ( varY + 0.00000) should sum decimals places on resulted Share this post Link to post
David Heffernan 2353 Posted April 9, 2023 (edited) 14 hours ago, David Heffernan said: Where in the question is a database mentioned? OK, there seem to be two questions asked by @Henry Olive The first one doesn't have any mention of a database, but has code that does not compile. The second question has database but we don't know what the values are. @Henry Olive you can't get a definitive answer unless we have precise details of what the data is. One thing we can say is that floating point multiplication is correct in Delphi. Edited April 9, 2023 by David Heffernan Share this post Link to post
Henry Olive 5 Posted April 9, 2023 Thank you SO much David, KodeZwerg, Programmer I solved the problem. Share this post Link to post