0

If I have

f: Single;
F := 0;
if F <> 0 then raise exception.create('xxx');

does this comparison will work fine in any platforms? I mean do I will need to do round(f) <> 0 in some platforms? I know that on Windows doing F <> 0 is fine because 0 is an integer but I m curious for other platforms

zeus
  • 12,173
  • 9
  • 63
  • 184
  • 1
    This will never ever raise. – Andreas Rejbrand Aug 18 '22 at 11:13
  • 1
    The value 0 is always exactly representable in all formats of floating point (that I know of). – HeartWare Aug 18 '22 at 11:22
  • @HeartWare Not really applicable to the above example, but while 0 is exactly representable, it might have more than 1 representation. For example, many floating point standard also support signed zeros (-0.0 and +0.0) and while some mandate to ignore sign while comparing zeros, I'm not sure all of them do. – Ken Bourassa Aug 24 '22 at 15:34

1 Answers1

1

In the title, you ask for a general answer, and in the body, you ask for a specific case. I'm not sure which answer you are trully interested in. But as a general case, the answer is "It depends".

As other have commented, your specific example will never raise, but it does not mean it's safe to compare a float to 0.

Take this exemple :

procedure TForm5.Button1Click(Sender: TObject);
var
  F: single;
begin
  F := (7 / 10);
  F := F - 0.7;
  if F <> 0 then
    raise Exception.Create('Error Message');
end;

This will (as far as I know) always raise.

Also, round(f) <> 0 wouldn't be the way to go about this. Comparevalue(F, 0, ????) <> EqualsValue would be.

As to the "why" of all this, this has been answered (probably numerous times) on SO. (you can start here)

Ken Bourassa
  • 6,363
  • 1
  • 19
  • 28
  • 1
    @Zeus Also have a look at this article: [Floating point numbers — Sand or dirt](http://rvelthuis.de/articles/articles-floats.html) – Blurry Sterk Aug 18 '22 at 13:11
  • 1
    You should almost certainly never use CompareFloat with a non zero tolerance. One of the great anti patterns. – David Heffernan Aug 18 '22 at 14:22
  • 1
    @DavidHeffernan I work on a system where I certainly always need to use a non zero tolerance because otherwise, I don't get the required result. Granted, that's mostly caused by the fact BCDs should have been used instead of Doubles. We don't all have the luxury of working on a utopically perfect codebase. And then, there are cases like this one `SameValue(0.2{as Single}, 0.2 {as Double})` that returns False when we most likely want True as a result. I understand why you say we should pass 0 and let the method compute the epsilon, it just never applied to any use case I've encountered. – Ken Bourassa Aug 18 '22 at 17:25
  • 1
    @ken If you want to compare 0.2 single vs 0.2 double then convert both to single and compare. CompareFloat is something of a travesty though. Anytime you need a tolerance there is usually a good solution to avoid having to choose that tolerance. And the way CompareFloat does it is opaque. I stand by what I said. – David Heffernan Aug 18 '22 at 17:46
  • @BlurrySterk thanks :) It's sad that Rudy Velthuis pass away :( – zeus Aug 18 '22 at 21:11