StrToFloat lazarus / 21-General ---------------------------------------------------------------------- Weitentaaal · 2021-07-06 12:38 Hello, so last time i used StrToFloat it realy confused me... what is this ??: Tx := 0,32 StrToFloat Wert= 0.319999993 why isn't there just 0.32 ?? why those useless Floatingpoints ??  is there any fix ? Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  Function TGlobals.Str2Float(Tx: String): Double;Var   Wert: Single;   Dummy, DeziTrenn: String;Begin   If Not OnlyNumeric(Tx) Then begin      Result := 0;      Exit;   end;    Dummy := Trim(FloatToStr(5/2));   DeziTrenn := Copy(Dummy, 2, 1);    IF (Pos(',', Tx) = 0) and (Pos('.', Tx) = 0) then begin      TryStrToFloat(Tx, Result);      Exit(Result);   end;    Tx := StringReplace(Tx, '.', DeziTrenn, [rfReplaceall]);   Tx := StringReplace(Tx, ',', DeziTrenn, [rfReplaceall]);    wert := StrToFloat(Tx); //This is what i meant    Wert := SimpleRoundTo(Wert); //just some tests   Wert := (trunc(StrToFloat(Tx) * 100)) / 100; //just some tests    //Wert := (StrToFloat(Tx) * 100 + 0.5) / 100;   Result := Wert;end; ---------------------------------------------------------------------- Okoba · 2021-07-06 12:52 It is how Floats are stored in float values, when you convert an string to a float value, it misses some accuracy and for example for double you have 64bit. This issue is independent from programming language or the compiler, it is fundamental thing in how float types works. For resolving it, you may use a proper rounding, it mostly fix this issue. If it is not enough, keep the string number, as string and only convert it to float when you need math methods. ---------------------------------------------------------------------- Weitentaaal · 2021-07-06 13:03 so why didn't this happen to my vb6 application ? Same Code different Result. i tested it with Global.Str2Float('0,32') ---------------------------------------------------------------------- Okoba · 2021-07-06 13:20 Probably its Str to float code round to the shortest value. Some compilers do that but the actual value is what FPC shows you. ---------------------------------------------------------------------- Weitentaaal · 2021-07-06 13:23 so how can i round this ?? i can't even do that.. Thaks for your Help btw.. appreciated ---------------------------------------------------------------------- Okoba · 2021-07-06 13:39 You are doing math stuff like multiplication, it will cause round error anyway, again as the limited size of float types. Note: Use double instead of single, it has much more precision. If these did not work, please share a standalone code so it can be test by someone like me. ---------------------------------------------------------------------- Zvoni · 2021-07-06 13:49 Not for the actual Issue, but why are you "manipulating" your String looking for the Decimal separator? StrToFloat/TryStrToFloat accepts a TFormatSetting-Parameter https://www.freepascal.org/docs-html/rtl/sysutils/tformatsettings.html https://www.freepascal.org/docs-html/rtl/sysutils/strtofloat.html https://www.freepascal.org/docs-html/rtl/sysutils/trystrtofloat.html FWIW, i'd use TryStrToFloat, since you can get a True/False if the conversion was successful ---------------------------------------------------------------------- Weitentaaal · 2021-07-06 14:13 Quote from: Zvoni on July 06, 2021, 03:49:10 pmNot for the actual Issue, but why are you "manipulating" your String looking for the Decimal separator? StrToFloat/TryStrToFloat accepts a TFormatSetting-Parameter https://www.freepascal.org/docs-html/rtl/sysutils/tformatsettings.html https://www.freepascal.org/docs-html/rtl/sysutils/strtofloat.html https://www.freepascal.org/docs-html/rtl/sysutils/trystrtofloat.html FWIW, i'd use TryStrToFloat, since you can get a True/False if the conversion was successful It's not my Function. It's from my co-worker ... imported from old programms and i just kept it. And i just replaced the seperator. Would this have a big inpact on my String ? could it be changed in it's coding (except for the changes i wanted to do)? An i have to change it because 0,3 is not a valid float for StrToFloat Quote from: OkobaPatino on July 06, 2021, 03:39:22 pmYou are doing math stuff like multiplication, it will cause round error anyway, again as the limited size of float types. Note: Use double instead of single, it has much more precision. If these did not work, please share a standalone code so it can be test by someone like me. Double was more acurate but i ended up with 0.32000000001 and i need the exact 0.32 of my value cuz they gave me a shitty as dll wich wants exact those values. i shared the Function in my very first post and all i do is call it after Form.Show with sample values like 0,32/0.32/2/1,0/1.0 Do i have to write myself a StringToFloat Function now ? ---------------------------------------------------------------------- Bart · 2021-07-06 15:00 Quote from: Weitentaaal on July 06, 2021, 04:13:09 pmDouble was more acurate but i ended up with 0.32000000001 and i need the exact 0.32 of my value cuz they gave me a shitty as dll wich wants exact those values. And how to pass this value to the dll then: as float or as string? Since 0.32 won't exactly fit into a double, nor in an extended, it would be impossible to pass the exact value 0.32 as some type of float to the dll. Bart ---------------------------------------------------------------------- Weitentaaal · 2021-07-06 15:09 Ok the thing is thy will Compare some values in the dll something like this: CurrVal = '0.32' then .......... a Coworker of mine just wrote the Accept Function wich should check the Values for Errors. i pass everything to this Function of the dll wich creates a String, wich gets passed to something else then calculation and at the end i get a String in return. Since today we never had this problem with VB6 but today we got this Problem because we were converting code from Vb6 to FPC. I just want to to get from this '0,32' (String) to this: 0.32  (Double/Single or whatever) ---------------------------------------------------------------------- dseligo · 2021-07-06 15:48 Maybe you can use Currency type, if 4 digits after decimal separator is enough for you: https://wiki.freepascal.org/Currency ---------------------------------------------------------------------- winni · 2021-07-06 16:20 Quote from: Bart on July 06, 2021, 05:00:34 pmQuote from: Weitentaaal on July 06, 2021, 04:13:09 pmDouble was more acurate but i ended up with 0.32000000001 and i need the exact 0.32 of my value cuz they gave me a shitty as dll wich wants exact those values. And how to pass this value to the dll then: as float or as string? Since 0.32 won't exactly fit into a double, nor in an extended, it would be impossible to pass the exact value 0.32 as some type of float to the dll. Bart Do you own calculation  to strip the decimals down to 2: assuming s is something like 0.32000000001 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var tmp: integer;....tmp := trunc (s*100);s := tmp/100;  Winni ---------------------------------------------------------------------- lucamar · 2021-07-06 16:44 Quote from: winni on July 06, 2021, 06:20:22 pmDo you own calculation  to strip the decimals down to 2: [... etc ...] That won't work since the problem is that 0,32 (as many other values) cannot be represented exactly as a float. As son as you make your:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i s := tmp/100;s (assuming it's of a float type) will again adquire a value of 0.32000000001 The real solution, if one must use floating point at all, is to never try exact matches but check for some adequately low value on e.g. a substraction:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if Abs(AValue - TestValue) < 0,00003 then ... But, of course, if someone out there gives you just a function signature  to which you pass values and he didn't take this into account inside the function you're S.O.L.D. ---------------------------------------------------------------------- winni · 2021-07-06 16:49 Hi! I don't know, where the problem is: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var d : double;begin   d := StrToFloat('0.32');   showMessage (FloatToStr(d));   end; I shows 0.32 and nothing else on a 64 bit machine. Winni ---------------------------------------------------------------------- Paolo · 2021-07-06 16:52 Try StrToFloatF and set the decimals you want. ---------------------------------------------------------------------- lucamar · 2021-07-06 17:34 Quote from: winni on July 06, 2021, 06:49:40 pmI don't know, where the problem is:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var d : double;begin   d := StrToFloat('0.32');   showMessage (FloatToStr(d));   end;I shows 0.32 and nothing else on a 64 bit machine. Hmmm ... Should have tested before shooting my mouth A little test: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program Project1; {$H+} uses SysUtils; var  s: single;  d: double;  sv: String;begin  s := 0.32;  WriteLn('Single: ', s.ToString);  d := 0.32;  WriteLn('Double: ', d.ToString);  sv := '0.32';  s := sv.ToSingle;  d := sv.ToDouble;  WriteLn('Str to Single: ', s.ToString);  WriteLn('Str to Double: ', d.ToString);end.gives this result: Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i Single: 0.3199999928Double: 0.32Str to Single: 0.3199999928Str to Double: 0.32So yeah, there should be no problem if one uses double everywhere. ---------------------------------------------------------------------- winni · 2021-07-06 20:15 Hi! If you insist in Single you have to remember to the time, when there were no classes and the system functions did what they should do: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var s : single;    st: string;begins := StrToFloat('0.32');Str(s:5:2, st);showMessage (st);end;               If you force system.str to 2 decimals it will round up to them. I think the easiest solution. And 50 years old. So grown up. Winni ---------------------------------------------------------------------- Weitentaaal · 2021-07-07 05:31 Thanks to everyone trying to help. i will try those solutions and Edit this Post if something helped. Edit : Tryed some of your Solutions, see attachments (Can't add more then 4 Attachments so its a zip). ---------------------------------------------------------------------- Weitentaaal · 2021-07-07 06:41 Hi, Tryed to check if there is a small divergence. If (StrToFloatDef(K[N], 0) = Value) or (((Value- StrToFloatDef(K[N], 0)) < 0.0000005) and ((Value- StrToFloatDef(K[N], 0)) < -0.0000005)) Then Begin worked fine but when the Variables had those Values: StrToFloatDef(K[N], 0) = 2.0 Value := 2.000000001 i got as difference (Value- StrToFloatDef(K[N], 0)) --> 5.0000000012537303e-008 Edit: i realised this was actually a very small floating point. But this still wont work Could someone tell me what i am doing wrong ? ---------------------------------------------------------------------- bytebites · 2021-07-07 07:13 Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i If (StrToFloatDef(K[N], 0) = Value) or (((Value- StrToFloatDef(K[N], 0)) < 0.0000005) and ((Value- StrToFloatDef(K[N], 0)) > -0.0000005)) Then ---------------------------------------------------------------------- lucamar · 2021-07-07 07:24 Quote from: bytebites on July 07, 2021, 09:13:00 amCode: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i If (StrToFloatDef(K[N], 0) = Value) or (((Value- StrToFloatDef(K[N], 0)) < 0.0000005) and ((Value- StrToFloatDef(K[N], 0)) > -0.0000005)) Then Rather easier on the eyes: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if Abs(Value - StrToFloatDef(K[N], 0)) < 0.0000005 then That takes care of the three conditions at once, at the (small) cost of a substraction. ---------------------------------------------------------------------- PascalDragon · 2021-07-07 07:47 Or one can use SameValue from unit Math: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if SameValue(Value, StrToFloatDef(K[N], 0), 0.0000005) then Note: if an Epsilon of 0 is used then a suitable value for the corresponding floating point type will be used. ---------------------------------------------------------------------- Weitentaaal · 2021-07-07 11:34 Nice thanks Works fine now with this workaround ---------------------------------------------------------------------- BobDog · 2021-07-07 13:06 Quote from: winni on July 06, 2021, 06:49:40 pmHi! I don't know, where the problem is: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i var d : double;begin   d := StrToFloat('0.32');   showMessage (FloatToStr(d));   end; I shows 0.32 and nothing else on a 64 bit machine. Winni I get this error: Error: Identifier not found "showMessage" (I have included sysutils for floatTostr) ---------------------------------------------------------------------- winni · 2021-07-07 14:39 Hi! You have to include the unit Dialogs in your uses section. Winni ---------------------------------------------------------------------- BobDog · 2021-07-07 15:09 Quote from: winni on July 07, 2021, 04:39:06 pmHi! You have to include the unit Dialogs in your uses section. Winni Thanks, but still the same error. Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i  program diag;usesdialogs,sysutils;var d : double;begin   d := StrToFloat('0.32');   showMessage (FloatToStr(d));end. ---------------------------------------------------------------------- winni · 2021-07-07 16:09 Hi! If you create a konsole programm you have to do i this way: program diag; uses sysutils; var d : double; begin    d := StrToFloat('0.32');    writeln(d); end.   Winni ---------------------------------------------------------------------- wp · 2021-07-07 16:11 Your program seems to be a console program, use WriteLn rather than ShowMessage Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i program diag;uses  sysutils;var   d : double;begin   d := StrToFloat('0.32');  // <---- DANGER: Works only when you live in a counter in which the decimal separator is a point!  WriteLn(FloatToStr(d));   // or  WriteLn(d:0:2);  WriteLn('Press ENTER to close');     ReadLn;end. ---------------------------------------------------------------------- devEric69 · 2021-07-07 18:15 Quote from: winni on July 06, 2021, 06:20:22 pmDo you own calculation  to strip the decimals down to 2: assuming s is something like 0.32000000001 [snip] It can be complicated, contextually, in fact. For information, IIRC, according to a simplification of the work of Chiu, Lee, and Mullis (rounding problems), there is a method that gives the relationship between the number of significant digits (say "m") and a requested rounding at the same place ("m", therefore). Pre-requisites: - any floating number y can be expressed as m*10^n . "m" is called the mantissa. This way of writing numbers is called scientific notation. For example, 120 = 1.2*10^2 (☜ we say, here, that we require 2 significant figures in the mantissa); 0.00324=3.14*10^-3 (☜ we say here that we require 3 significant figures in the mantissa; m=3) - any floating number can be rounded to the "r" figure. For example, rounding 0.582 to 1 figure after the decimal point = 0.6 (☜ we say that r=1); rounding 4.882 to 0 digits after the decimal point = 5; rounding 12783 to -2 digits after the decimal point = 12800. So, if you want to round to the significant number m (that we want to keep), we can use this relationship (Excel style, SQL style): Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i round(value; m - (1 + FLOOR(LOG_10(ABS(value))))) For example: value=1.2783*10^4               ⇧ if we decide that we want to keep only 3 significant numbers, we can code:                  round(value; 3 - (1+4) = 3 - 5 = -2) = round(value; -2) ---------------------------------------------------------------------- Weitentaaal · 2021-07-08 07:43 Quote from: devEric69 on July 07, 2021, 08:15:42 pmQuote from: winni on July 06, 2021, 06:20:22 pmDo you own calculation  to strip the decimals down to 2: assuming s is something like 0.32000000001 [snip] It can be complicated, contextually, in fact. For information, IIRC, according to a simplification of the work of Chiu, Lee, and Mullis (rounding problems), there is a method that gives the relationship between the number of significant digits (say "m") and a requested rounding at the same place ("m", therefore). Pre-requisites: - any floating number y can be expressed as m*10^n . "m" is called the mantissa. This way of writing numbers is called scientific notation. For example, 120 = 1.2*10^2 (☜ we say, here, that we require 2 significant figures in the mantissa); 0.00324=3.14*10^-3 (☜ we say here that we require 3 significant figures in the mantissa; m=3) - any floating number can be rounded to the "r" figure. For example, rounding 0.582 to 1 figure after the decimal point = 0.6 (☜ we say that r=1); rounding 4.882 to 0 digits after the decimal point = 5; rounding 12783 to -2 digits after the decimal point = 12800. So, if you want to round to the significant number m (that we want to keep), we can use this relationship (Excel style, SQL style): Code: Text  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i round(value; m - (1 + FLOOR(LOG_10(ABS(value))))) For example: value=1.2783*10^4               ⇧ if we decide that we want to keep only 3 significant numbers, we can code:                  round(value; 3 - (1+4) = 3 - 5 = -2) = round(value; -2)      yes i understand your calculation but the Functions like round just seem like they do nothing to my value. Seems like they have an Exit imediately after the begin. value := 0.320000005 = (should be --> 3.20000005*10^-1 if i don't mistake) round it would bring me back to 0.320000005 (this is what i don't understand) In theorie : round(value; 2 - (1+1) = 2 - 2 = 0)  (don't exactly know what u did here bc my equation is definitely wrong XD) = round(value; 0)  //would make Sense bc i get same value as before would it make sense to rewrite StrToFloat just for this specific case ? and would it even be possible to do a precise round? ---------------------------------------------------------------------- wp · 2021-07-08 08:29 You do not seem to understand floating point numbers. In mathematics, "real" numbers are infinetely dense. This means that if you pick two distinct numbers there are infinitely many numbers between them. In a computer, this is not valid any more because there is a finite number of bits to represent the number. Therefore, floating point values in a computer exist only on some kind of discrete "grid". Fact is that the value 0.32 simply does not exist in the computer because it cannot be represented exactly as a float. What you get is the closest "grid" value, 0.320000005 (assumed). So, whatever you do to recreate the float 0.32 you will always produce the grid value 0.320000005. Do not confuse floating point number with their string presentation which can be formatted to any number of decimal places. ---------------------------------------------------------------------- devEric69 · 2021-07-08 08:32 Quote from: Weitentaaal on July 08, 2021, 09:43:23 amwould it make sense to rewrite StrToFloat just for this specific case ? and would it even be possible to do a precise round? Hello, No, it wouldn't make sense. Don't bother with my answer! My post is largely off-topic, but it was to illustrate that rounding problems are still the subject of scientific (mathematical) research. So, concerning my reported trick, it must be used in SQL scripts (if one forgot to use the fields of type currency, if numeric data were recorded in string fields, if the data-fields contain a lot of useless insignificant figures, ...), or in reporting \ calculation sheets tools (which also do their own calculations, resulting in annoying significant numbers)... It's to do a sort of "sanetarization" of the result of several calculations to compare them properly (once the correct base-10 comparison dimension has been chosen), in such tools. A bit like the Pascal functions designed to do number formatting for accounting calculations. On the pure Pascal programming side, really, others have already answered with much more intelligent and adapted answers to the original question (string type towards floating type) than I did, and answers that work well in Pascal. ---------------------------------------------------------------------- Weitentaaal · 2021-07-08 08:54 Ok then i have to find a workaround i guess .. But much thanks to all of your repys ... appreciated. ---------------------------------------------------------------------- jamie · 2021-07-08 10:55 Here is a little currency helper I use when dealing with Excel type math or what MS deems to be the correct way of doing things in Excel.  Attached is  a demo and if you want to use the helper simply copy the record and associated methods over to a unit of your own to use it in your code.  The demo shows how to do selective rounding, summing, flooring, etc...     All test was checked against Excel for correctness. ---------------------------------------------------------------------- Weitentaaal · 2021-07-09 08:24 Thanks @Jamie very Helpful