3 ms·
From a user POV, I think == and === on floats should simply be undefined in any language. It should be a compile time or runtime error. There can be a separate
by chubot 3y ago
From a user POV, I think == and === on floats should simply be undefined in any language. It should be a compile time or runtime error.
There can be a separate function `float_equals()` with explicit args that does what people want
The only reason to use the same syntax == is for POLYMORPHIC code that is actually correct.
But it's not going to be correct with floats, because they don't obey the same algebraic laws ... So the syntax should be different!
---
I believe the Erlang compiler optimization presented as justification for this change is a good example
The compiler wants to reason about code, independent of types
But that reasoning about the =:= operator is wrong for the float case.
- kragen 3y agowhat people want varies, but often what people doing numerical programming want is to write their monomorphic code in infix syntax so they can more easily see bugs in it they're already familiar with rounding errors from that perspective you're suggesting taking a step backwards from fortran i toward assembly language the erlang compiler bug presented is not an example of what you're talking about because you're talking about arithmetic, and the buggy comparison operator it's using is not an arithmetic comparison operator
- chubot 3y agoFortran would be an interesting case, because say C++ is polymorphic, and so are all dynamic programming languages with more than 1 type (x == y could be a string or float comparison) But I would still say that floating point equality is a vanishingly rare operation I can't think of any real use case for it, other than maybe some (bad, incomplete) unit tests that assert 1.0 == x and assert 1.0 == y And that use case is perfectly served by float_equals(), and arguably served better if it has some options. Although probably abs(x - y) < eps is just as good, and you don't even need float_equals() --- Can you show some real use cases for floating point equality in good, production code? (honest question) It's similar to hashing floats, which Go and Python do allow. I made an honest request for examples of float hashing: https://lobste.rs/s/9e8qsh/go_1_21_may_have_clear_x_builtin#c_hbqltt https://lobste.rs/s/9e8qsh/go_1_21_may_have_clear_x_builtin#... https://old.reddit.com/r/ProgrammingLanguages/comments/10bm2w9/bitwise_equality_of_floats/j4bvrkd/ https://old.reddit.com/r/ProgrammingLanguages/comments/10bm2... I didn't get any answers that appeared realistic. Some people said you might want to create a histogram of floats -- but that's obviously better served by bucketing floats, so you're hashing integers. Another person said the same thing for quantizing to mesh. One person suggested fraud detection for made-up values, but that was clearly addressed by converting the float to a bit pattern, and hashing the bit pattern. ---- This isn't a theoretical question since we're working on this for https://www.oilshell.org https://www.oilshell.org. For that case it seems pretty clearly OK to omit === on floats, since I use awk and R for simple stats and percentages, and that's likely what people would do with a shell. Though as always I'm open to concrete counterexamples.
- kragen 3y agoi gave some examples in https://news.ycombinator.com/item?id=35883963 https://news.ycombinator.com/item?id=35883963, though arguably those are not very concrete. also i pointed out there why unit tests that use exact comparison on floats are not necessarily bad: ieee-784 specifies bit-exact results for the five fundamental arithmetic operations, and if your compiler is introducing rounding errors, you want your tests to fail. (or introducing nonerrors, in the case where it's introducing fmas.) even hashing is useful for memoization i think probably you're asking in the wrong places the lapack source might be a better place to look; we can probably suppose that if something is in lapack it's realistic and also not a bug, and numerical code doesn't get more 'good, production' than lapack in dgelsx for example i find ELSE IF( ANRM.EQ.ZERO ) THEN * * Matrix all zero. Return zero solution. * CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) and also (fairly dubious, at least to my uneducated eye) * Determine RANK using incremental condition estimation * WORK( ISMIN ) = ONE WORK( ISMAX ) = ONE SMAX = ABS( A( 1, 1 ) ) SMIN = SMAX IF( ABS( A( 1, 1 ) ).EQ.ZERO ) THEN RANK = 0 CALL DLASET( 'F', MAX( M, N ), NRHS, ZERO, ZERO, B, LDB ) GO TO 100 ELSE RANK = 1 END IF as well as some sentinel-value checks and in dlar1v: WORK( INDS+I ) = S*WORK( INDLPL+I )*L( I ) IF( WORK( INDLPL+I ).EQ.ZERO ) $ WORK( INDS+I ) = LLD( I ) and also TMP = D( I ) / DMINUS IF(DMINUS.LT.ZERO) NEG2 = NEG2 + 1 WORK( INDUMN+I ) = L( I )*TMP WORK( INDP+I-1 ) = WORK( INDP+I )*TMP - LAMBDA IF( TMP.EQ.ZERO ) $ WORK( INDP+I-1 ) = D( I ) - LAMBDA and also IF( ABS(MINGMA).EQ.ZERO ) $ MINGMA = EPS*WORK( INDS+R1-1 ) of course float comparisons for ordering are much more common than float comparisons for equality, but there are numerous realistic examples of float comparisons for equality in lapack and, i think, in applied mathematics in general but if you ask an audience of type theorists, sysadmins, and web developers, they won't know that; they aren't numerical analysts and probably haven't inverted a submatrix since sophomore math class, if ever (there are 6550 files in lapack 3.9.0 of which i looked through 15 to find these examples, suggesting that there are on the order of 1000 realistic examples in there; eventually i'd probably find one that wasn't even comparing to zero) plausibly instead of giving them floating point by default you should give them fixed point with, say, nine digits after the decimal point; that was the approach knuth took in tex, for example, to guarantee reproducibility, but it also gives human-predictable rounding. and in most cases it should be perfectly adequate for simple stats and percentages. as a bonus you get 64 bits of precision instead of 53