ŁukaszDe 38 Posted March 27 (edited) Hi I found today a problem with IsZero method: Here is comparison last version of D11 and D12: Edited March 27 by ŁukaszDe Share this post Link to post
Uwe Raabe 2057 Posted March 27 As far as I can see there are no changes in the implementation. Also a quick console example shows no regression. Can you please provide the source for your test case to verify? BTW, could it be only a problem with Watch Variables? 1 Share this post Link to post
ŁukaszDe 38 Posted March 27 Right, Watch list showing False but in code it is entering to if statement with IsZero(czas_przejazdu, 1e-3) where czas_przejazdu = 0. Share this post Link to post
Rollo62 536 Posted March 27 Could this have something to do with it? https://blog.marcocantu.com/blog/2023-october-nativeint-weak-alias.html Like Uwe said, a little more code would be nice. Share this post Link to post
darnocian 84 Posted March 28 (edited) Floating point is always fun. Math.IsZero has 3 overloads for different types - extended, double, single With a simple test app on Delphi 12: program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.Math, System.SysUtils; procedure Test; var e: extended; d: double; s: single; te, td, ts: boolean; begin e := 3.5527136788055E-15; d := 3.5527136788055E-15; s := 3.5527136788055E-15; te := iszero(e); td := iszero(d); ts := iszero(s); end; begin try Test; except on e: Exception do Writeln(e.ClassName, ': ', e.Message); end; end. On Win32, I was surprised that 'te' is false. On Win64, the values are as expected. Something to note for those that don't know. In Win64, 'extended' is 64bit like 'double', where on Win32 it is 80bit. I didn't check between versions, but is the resolution the same? Squirrelled away on line 5290 in System.Math, there is: const FuzzFactor = 1000; SingleResolution = 1E-7 * FuzzFactor; DoubleResolution = 1E-15 * FuzzFactor; {$IFDEF EXTENDEDHAS10BYTES} ExtendedResolution = 1E-19 * FuzzFactor; {$ELSE !EXTENDEDHAS10BYTES} ExtendedResolution = DoubleResolution; {$ENDIF !EXTENDEDHAS10BYTES} IMO I think those consts should probably be variables and in the interface section so they can be overridden if required. It does look like something buggy happening with the 'Extended' type on win32... I played with SameValue and Compare( which uses SameValue), which didn't look bad. SameValue/Compare take an Epsilon (the resolution). Stepping through IsZero, what I spotted in the debugger: if Epsilon = 0 then Epsilon := ExtendedResolution; After the assignment to Epsilon, Epsilon was 0 and not 1e-16. On 64bit, Epsilon becomes 1e-12. So something funky with the codegen? I recall some changes to FP operations in the new compiler, but I can't recall offhand. Edited March 28 by darnocian Share this post Link to post
darnocian 84 Posted March 28 (edited) I was looking at docs: https://docwiki.embarcadero.com/Libraries/Athens/en/System.Extended I'm not a fan of the type being so different between platforms. My memory is still 64kb, so am relying too much on ChatGPT these days 😉 There is float32 and float64... maybe making a few more types indicating how many bits can also help make the size a bit more obvious. Edited March 28 by darnocian Share this post Link to post
Sherlock 663 Posted March 28 OK here's what I don't get. Seeing this const FuzzFactor = 1000; SingleResolution = 1E-7 * FuzzFactor; DoubleResolution = 1E-15 * FuzzFactor; I have to ask myself, why not const SingleResolution = 1E-4; DoubleResolution = 1E-12; Sure the calculation happens only once, and FuzzFactor seems to explain a magic number but then we still have those other magic numbers... just an observation. Share this post Link to post
David Heffernan 2345 Posted March 28 The best way to deal with this is never to call any of these functions in the first place, they are all useless 1 Share this post Link to post
Uwe Raabe 2057 Posted March 28 49 minutes ago, Sherlock said: we still have those other magic numbers Actually, they are not that magic: 1 Share this post Link to post
darnocian 84 Posted March 28 1 hour ago, David Heffernan said: The best way to deal with this is never to call any of these functions in the first place, they are all useless What do you mean by useless? Just not liking the specific implementation? Share this post Link to post
David Heffernan 2345 Posted March 28 51 minutes ago, darnocian said: What do you mean by useless? Just not liking the specific implementation? This entire approach of applying some arbitrary epsilon is rubbish. I can't imagine any scenarios where they'd be useful and I've only ever seen them used inappropriately. Share this post Link to post
Uwe Raabe 2057 Posted March 28 2 minutes ago, David Heffernan said: This entire approach of applying some arbitrary epsilon is rubbish. I beg to differ here. The approach is to have a decent epsilon when no one is given. It doesn't prohibit anyone to give an epsilon appropriate to the current scenario. 12 minutes ago, David Heffernan said: I've only ever seen them used inappropriately The default values currently used actually cover a common beginner's mistake assuming that floats can be compared for exact equality. Usually the IsZero implementation works pretty good for the majority of the cases - at least those I encountered myself. Perhaps you just never stumbled about code using them appropriately? 1 Share this post Link to post
David Heffernan 2345 Posted March 28 10 minutes ago, Uwe Raabe said: The default values currently used actually cover a common beginner's mistake assuming that floats can be compared for exact equality. Floats can be compared for exact equality, in plenty of circumstances. The beginner mistake is to use some epsilon value without any sound rationale for it. 10 minutes ago, Uwe Raabe said: Usually the IsZero implementation works pretty good for the majority of the cases Usually, and works pretty good, and for the majority of cases doesn't sound great with my numerical programming head on. Share this post Link to post
darnocian 84 Posted March 29 (edited) The rationale for it is when it comes to rounding due to the way the float is represented with limited bits... there will be to mismatches. You may be lucky, and comparison may work, but the epsilon comparison approach is a failsafe method to cater for rounding issues in the process of various calculations. Here is a simple example. procedure Test; var d: double; d2: double; diff: double; v, v2: double; begin d := 1.0000002; d2 := 1.0000001; v := 0.0000001; v2 := 0.0000001; diff := d - d2; // 9.99999998363421e-08 assert(v = v2); // values do match assert(diff <> v); // doesn't match because of rounding assert(SameValue(diff, v)); end; above done on win32. I aligned the numbers on purpose... if we do the math, we can see v should be d-d2. v = v2 is true.... then noddy calculation, we have diff = d-d2... and diff <> v, but SameValue with the epsilon shows with the given precision, we assume the numbers to be the same. Edited March 29 by darnocian Share this post Link to post
David Heffernan 2345 Posted March 29 7 hours ago, darnocian said: The rationale for it is when it comes to rounding due to the way the float is represented with limited bits... there will be to mismatches. You may be lucky, and comparison may work, but the epsilon comparison approach is a failsafe method to cater for rounding issues in the process of various calculations. I know how floating point math works, it's been what I've done for a living for the past 30 years. Using arbitrary epsilon values is not failsafe and relies on luck. Share this post Link to post
Attila Kovacs 629 Posted March 29 22 minutes ago, David Heffernan said: I know how floating point math works, it's been what I've done for a living for the past 30 years. You wanted to make your math lib available for the public, back in the days. Still waiting 😛 Share this post Link to post
David Heffernan 2345 Posted March 29 1 hour ago, Attila Kovacs said: You wanted to make your math lib available for the public, back in the days. Still waiting 😛 I don't have a math lib that is publishable. I've never wanted to have or do such a thing. You must be mis-remembering. Share this post Link to post
darnocian 84 Posted March 29 7 hours ago, David Heffernan said: I know how floating point math works It isn't all about you. I'm just sharing. Glad you know. Share this post Link to post
darnocian 84 Posted March 29 (edited) 7 hours ago, David Heffernan said: Using arbitrary epsilon values is not failsafe and relies on luck. mainly on what solution thinks is acceptable. These are all tools. we can choose to use what we want, but just need to know the limitations. Edited March 29 by darnocian Share this post Link to post
Brandon Staggs 278 Posted March 29 23 hours ago, David Heffernan said: This entire approach of applying some arbitrary epsilon is rubbish. I can't imagine any scenarios where they'd be useful and I've only ever seen them used inappropriately. What's your approach? Share this post Link to post
Attila Kovacs 629 Posted March 29 6 hours ago, David Heffernan said: I don't have a math lib that is publishable. I've never wanted to have or do such a thing. You must be mis-remembering. I read something in so from you but I can't find it, it was about the whole rtl float handling is rubbish or something like that. Not sure about the details. Share this post Link to post
Anders Melander 1783 Posted March 29 1 hour ago, Attila Kovacs said: I read something in so from you but I can't find it, it was about the whole rtl float handling is rubbish or something like that. Not sure about the details. Opinions are easy. Code... a bit harder. 1 Share this post Link to post
David Heffernan 2345 Posted March 29 3 hours ago, Attila Kovacs said: I read something in so from you but I can't find it, it was about the whole rtl float handling is rubbish or something like that. Not sure about the details. Well, that's true. Lots of thread safety issues with how it handles floating point control status. But that's not that same as having a math lib. Share this post Link to post
darnocian 84 Posted March 30 I'm still interested to know more about any alternatives to using epsilon for comparison. I've only seen subtle variations on the same theme, and always keen to learn something new. Share this post Link to post
David Heffernan 2345 Posted March 30 21 minutes ago, darnocian said: I'm still interested to know more about any alternatives to using epsilon for comparison. I've only seen subtle variations on the same theme, and always keen to learn something new. It depends on what you are comparing, what algorithms are involved etc. Share this post Link to post