Live data from Hacker News

In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

erlangforums.com

81–90 of 236 posts

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#81

Earlier quoted context omitted.

Well, I assume you want to sell your hard-earned stocks of civilization-helping companies sometimes...

Nope. I'd rather there not be a thing called a stock market at all.

Do you just plan to save your money in dollar bills hidden inside a pillow until you retire? If you want to invest it in any way, you probably want to avoid floating point numbers for keeping track of it.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#82
post #40
post #38

Earlier quoted context omitted.

I would add generating large financial reports, enterprise billing etc. There is a huge business effect between for example 2 hours needed to calculate monthly invoices and 24 hours.

Is any of that actually bottlenecked by arithmetic rather than pointer chasing?

Probably more likely inefficient data access patterns, such as N+1 queries, inefficient algorithms, lack of parallelism

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#83
post #14

Earlier quoted context omitted.

They meant using the equal operator, because floating point is inexact and can produce different representations for the same number depending on how it was obtained. Greater and less than are fine. Equal is usually implemented by seeing if a number fits inside a tight range.

Every finite floating point value precisely represents an exact quantity. Arithmetic isn't lossless though. This isn't a special property of floats. Decimals behave the same way.

I was with you until the end

First point: FPs are unique. Clearly true

Second point: Combing FPs isn't lossless, across most/all arithmetic. Clearly true, the root of our discussion

Third point: decimal arithmetic is lossy too. Strongly disagree. The system of representation is what is lossy - floating point. Arithmetic (between two decimal numbers) is clearly not lossy in and of itself, only as implemented with computers.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#84
post #3

As a general rule, if you find yourself comparing floating point numbers, that's probably not what you want. I'm wondering what they are going to do with other operators, >=, <= etc

In general, this is good advice. However, there are cases where comparing floating point numbers for equality works just fine. For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Or if you have a sentinel value -1.0, it is perfectly ok to do 'if (a == -1.0)' In general, if you look for a number 'f' in variable 'v', you can s…

> For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change.

Isn't it strictly faster to simply assign? No branching, no branch predictions, only one instruction in all cases.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#85

Earlier quoted context omitted.

Zero is zero, but signs are a direction. There are multiple parts to numbers. Stand in place and turn around: how far did you go from where you started? Nonetheless, I agree. It's a bad idea.

By that logic there should be e.g. +4.0 and +4.0- (for when you go 4m forwards vs when you go 4m forwards but also turn around at the end).

In vector maths, this would just be +4.0.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#86

Earlier quoted context omitted.

It is 2023 and our tooling still encourages the same mistakes people were making 40 years ago. Can we really not have equality operators that do a comparison with a 1% tolerance or something as a sensible default equivalence instead of blatantly wrong bitwise comparison? I would even be happy with a default set of compiler warnings or errors, which I don’t believe I have ever seen.

The problem with defining an “epsilon” (1% in your case) is that there is no value that would please everyone. For some, 1% will be fine, but others may need 0.0001%. The solution is to either use decimal floats if they suit your need (and eat the performance penalty), or to use a linter that flags float comparisons by equality.

That’s bad enough, but it is not the problem with defining an “epsilon”, it’s a problem.

Another one is that you would lose transitivity on equality. With a 1% epsilon, you would have

   1.000 == 1.005
   1.005 == 1.010
   1.010 == 1.015
 
but

   1.000 != 1.015
You also would have to be careful on how to define that 1% error range. the naive "x is equal to all numbers between 0.99x and 1.01x" would mean 1.0 would be considered equal to 0.99, but 0.99 would not be considered equal to 1.0 (1.01 times 0.99 is less than 1.0)

You also lose that, if a == b and c == d it follows that a + c == b + d.

The behavior around zero also will go against intuition. If you consider 0.99 and 1.0 to be equal, do you really want 1.0E-100 and -1.0E-100 be different?

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#87
post #84

Earlier quoted context omitted.

In general, this is good advice. However, there are cases where comparing floating point numbers for equality works just fine. For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Or if you have a sentinel value -1.0, it is perfectly ok to do 'if (a == -1.0)' In general, if you look for a number 'f' in variable 'v', you can s…

> For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Isn't it strictly faster to simply assign? No branching, no branch predictions, only one instruction in all cases.

Assuming that all you want to do is assign, then sure. If you want to log the change or do any additional conditional logic, then that wouldn't work.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#88
post #3

As a general rule, if you find yourself comparing floating point numbers, that's probably not what you want. I'm wondering what they are going to do with other operators, >=, <= etc

In general, this is good advice. However, there are cases where comparing floating point numbers for equality works just fine. For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Or if you have a sentinel value -1.0, it is perfectly ok to do 'if (a == -1.0)' In general, if you look for a number 'f' in variable 'v', you can s…

I know there is a fair bit of division on this point but I've always liked type mixing, in languages where this is available, to handle signal values and preferred separate variables where it is not. I'd prefer to `if (v IS NULL)` a nullable float compared to checking a constant value - or else to use a guard value to test the validity i.e. `if x = FREQUENCY_SET // enter logic involving the frequency stored in v` - that approach is even better if you can use tuples/structs to glue the status and value fields together.

I am a quickly crustifying developer who was an enthusiatic value packer in their younger years but I've changed my tune to be less afraid of using more variables if they are clearer - even if that comes at a cost to data efficiency (and like, an extremely negligible cost in most situations). Though I don't have any objections to value packing for serialization - that's a fundamentally different domain.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#89
post #84

Earlier quoted context omitted.

In general, this is good advice. However, there are cases where comparing floating point numbers for equality works just fine. For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Or if you have a sentinel value -1.0, it is perfectly ok to do 'if (a == -1.0)' In general, if you look for a number 'f' in variable 'v', you can s…

> For example, if you have a variable 'v' and want to update it to a new value 'f', you can do 'if (v == f)' to check if the variable would change. Isn't it strictly faster to simply assign? No branching, no branch predictions, only one instruction in all cases.

It depends on whether you need a set operation or a test-and-set operation.

Re: In Erlang/OTP 27, +0.0 will no longer be exactly equal to -0.0

#90
post #3

As a general rule, if you find yourself comparing floating point numbers, that's probably not what you want. I'm wondering what they are going to do with other operators, >=, <= etc

I've always held that the numbers themselves are perfectly precise. It's the operations that don't do what you expect. Of course, that observation may be more or less useful, depending on circumstances.

How do you define numbers in a meaningful way without involving operators?

Without operators, all you have is a set of objects which you can't tell apart.

Post reply on HN