Skip to main content
32 events
when toggle format what by license comment
Jan 17, 2021 at 17:00 comment added gnasher729 And for sorting, there is no reason not to sort by the exact floating point value but do something more complicated.
Jan 17, 2021 at 16:55 comment added gnasher729 To handle NaN, I’d recommend using =,< etc. according to IEEE; sorting an array by a floating-point value should put NaNs all at the beginning or all at the end of the array, and for dictionaries with a floating point key consider all NaNs equal to each other so any object can be added to a dictionary, make sure that all NaNs have the same hash code, and +0 and -0 have the same hash code. Things get interesting when you have “optional<double>” as a type, where nil and NaN are different.
Oct 23, 2020 at 19:29 comment added leftaroundabout @EricDuminil both sqrt(-1) and sqrt(-2) are conceptually (in reals) error cases – arguably they should just raise an exception, which is kind of what you get with signalling NaNs. Quiet NaNs are used as a compromise, to avoid any branching overhead but still make sure errors never go unnoticed. I quite like the idea of extending that to booleans too. The law of excluded middle is overrated – not only are proof assistants like Coq doing away with it. also both safe floating-point usage and exception propagation can be seen in a similar light as non-classical logic.
Oct 23, 2020 at 7:52 comment added Mario Carneiro @EricDuminil Note that even "regular" numbers in IEEE-754 don't satisfy the archimedean property; if you keep adding 1's you will eventually run out of precision (at which point you get n+1 = n), before hitting the largest representable finite value.
Oct 22, 2020 at 21:11 comment added supercat @EricDuminil: The operator "+" doesn't yield the arithmetic sum, but rather the representable value which is "nearest", according to rounding rules, to the arithmetic sum if the latter is defined and within range of the type. If the numerical value of +tiny is infinitesimally greater than zero, then +tiny+tiny would be closer to that than to the next larger value, and would thus be rounded back to +tiny.
Oct 22, 2020 at 21:01 comment added Eric Duminil @supercat tiny + tiny cannot be tiny, because if you keep adding tiny, you should be able to reach any number. See en.m.wikipedia.org/wiki/Archimedean_property
Oct 22, 2020 at 20:54 comment added supercat ...with the asymmetric behavior of the IEEE-754 signed zeroes, which don't even guarantee things like equivalence between x-y and -1*(y-x).
Oct 22, 2020 at 20:51 comment added supercat @EricDuminil: +Tiny+tiny yields +tiny. +tiny-tiny yields additive-identity zero. and tiny * inf or zero * inf yields NaN. The only "iffy" cases I can see would be +inf-x and -inf+x [for numerical x>0], which the present Standard handles by yielding an infinity of the same sign as the original--behavior which may sometimes yield results that are less meaningful than they would appear, and cases like 1/(+tiny+tiny-tiny-tiny), which would yield -inf, but could have yielded NaN or +Inf if the operations were performed in a different sequence. Those problems are small, however, compared...
Oct 22, 2020 at 20:37 comment added Eric Duminil @supercat: What would tiny+tiny be? What would tiny*inf be? How many tiny would you need in order to get to 1.0?
Oct 22, 2020 at 20:26 comment added supercat @EricDuminil: The fact that existing hardware uses IEEE-754 would make it impractical without hardware designed for it, but I don't see that there would have been any particular difficulty supporting it had IEEE specified things that way. Use exponent bit pattern of 0001 rather than zero as the "denormal" indicator, all-bits-zero to indicate zero, and a combination of an all-bits-zero exponent and a certain bit set in the mantissa as NaN. What aspects would not have been practical to implement?
Oct 22, 2020 at 20:16 comment added Eric Duminil @supercat: AFAICT, your +-tiny idea could never work in practice. Did you every try to implement it? I'd be happy to be proved wrong.
Oct 22, 2020 at 16:45 comment added supercat ...respect to the fact that NaN!=NaN, but also with respect to the fact that x==y does not imply that 1/x==1/y. Two values should only be regarded as equivalent if they will behave identically in all circumstances; the values 1/+Inf and 1/-Inf will behave differently if each is divided into 1.
Oct 22, 2020 at 16:42 comment added supercat ...some other kind of blob based purely on the contents of the former, and has a means of building an equivalence-mapped collection, one can build a cache of all of the distinct blobs that have been fed to the function along with their associated outputs, without having to know or care about what any of the data in the input or output blobs means. Such a collection will blow up when using floating-points if the inputs could be NaN, because every time the function is invoked with NaN would generate another entry in the collection. Note that IEEE floating-point is broken not only with...
Oct 22, 2020 at 16:39 comment added supercat @Caleth: One specifies that if either operand to + is some kind of NaN, the result will be likewise; the result will also be NaN if the first operand is +Inf and the other is -Inf or vice versa. Otherwise, the operator + yields the member of the equivalence class which is arithmetically closest to the arithmetic sum of the nominal value of the operands. The notion of an equivalence class is fundamental to many programming tasks which would care nothing about the objects being compared beyond equivalence. For example, if one has a function which accepts a blob and yields...
Oct 22, 2020 at 16:24 comment added Caleth @supercat what do you propose for the infinity of operations that are only defined for a subset of doubles?
Oct 22, 2020 at 16:04 comment added Eric Duminil @supercat your proposal is interesting, but I don't see how it could solve the underlying problem : you still need to somehow represent uncountably many numbers with a fixed amount of bits, no matter if 32, 64 or 128 bits. Also, sqrt(-1) and sqrt(-2) are clearly distinct, and shouldn't belong to the same NaN class, so a flag wouldn't do. The current system isn't perfect, but I suppose that no system could be perfect. And at least NaN works as a big "There be dragons. Forget equivalence classes" sign.
Oct 22, 2020 at 15:50 comment added supercat @Caleth: If one wants infinitesimals to work properly, both positive and negative infinitesimals need to be distinct from zero, rather than having zero behave like positive infinitesimal. There is no fundamental reason why floating-point numbers can't behave as an algebraic construct with an equivalence relation; all of the floating-point formats I've used that aren't based on IEEE-754 do precisely that. The fact that it's possible for x+y==x+z to be true when y!=z isn't really a breakage means that + isn't an algebraic group operator, but not all algebraic constructs need to be groups.
Oct 22, 2020 at 15:43 comment added supercat ...would have been any difficulty replacing signed zeroes with infinitesimals ("tiny") which would be distinct from an additive-identity zero? So 1/+Inf would yield +tiny, and 1/-inf would yield -tiny, 1/+tiny would yield 1/+inf, and 1/-tiny would yield -inf, but 1/0 would yield NaN, and 1/x==1/(0+x)` would be true for all x If x==NaN were true only when x was the same NaN, and x<>NaN were false for all x, I'd define infinitesimal comparisons so +tiny==0, +tiny<0, +tiny>0, +tiny<>0, and +tiny<=0 would be false, but +tiny>=0 would be true.
Oct 22, 2020 at 15:41 comment added Caleth @supercat comparisons involving IEEE 754 floating point numbers are "broken" in the same sense that arithmetic on the reals is "broken"
Oct 22, 2020 at 15:37 comment added Caleth @supercat my basic point was to not make == any worse. NaN is compromise. How would you make a total function out of /?
Oct 22, 2020 at 15:32 comment added supercat @MSalters: ...the IEEE spec mandates that neither == and != can be used as an equivalence relation. BTW, given that many languages used <> as their non-equal operator, having the equality operator test equivalence and the inequality operator test for ordered difference might have been the most logical approach, so if x and y are the results of separate operations yielding NaN, x==x (and y==y) would be true, x<>x and x<>y would be false, and x==y could be either true and false, but would behave consistently for any particular x and y). BTW, I wonder if there...
Oct 22, 2020 at 15:31 comment added supercat @MSalters: It may be useful to have a comparison operator that yields a true/false/unknown output, yielding the latter when fed a NaN, but the concept of a mapping collection is only meaningful for sets that have a defined equivalence relation. It may be reasonable to have a set of comparison operators where NaN==NaN would yield false but NaN!=NaN would also yield false and x!=NaN would yield true if x isn't NaN; code could then use either x==y or !(x!=y) depending upon what kind of comparison it needed (thus allowing the latter to be used as an equivalence test), but...
Oct 22, 2020 at 15:29 comment added Caleth @supercat == over { NaN } is vacuously transitive, because the relation is empty
Oct 22, 2020 at 15:26 comment added supercat @EricDuminil: any comparison method that never reports anything in a set equal to anything--not even itself--will never be non-transitive with respect to members of that set. Transitivity is thus rather useless without reflexive identity.
Oct 22, 2020 at 15:23 comment added supercat @EricDuminil: The most important aspect of an equivalence relation is reflexive identity: for any x, x==x. An implementation which uses different NaN bit patterns for different purposes could decide to partition them into equivalence sets in any convenient fashion without breaking the == equivalence relation, but treating all NaNs as lumping them together for purposes of equivalence would be no worse than the present situation which allows no means of distinguishing them. As for Transitivity, I guess there might not be any scenarios where the present scheme is non-transitive, but...
Oct 22, 2020 at 11:15 comment added Eric Duminil @MSalters: I thought about that too. But NaB would basically break the law of excluded middle, and it would make every boolean logic so much harder. It would be like checking for null before every boolean expression.
Oct 22, 2020 at 9:09 comment added MSalters To combine NaN with ==, you need NaB - not a Boolean. The fundamental idea of NaN is that it propagates through calculations, and that means it has to propagate through expressions involving booleans as well.
Oct 22, 2020 at 6:59 comment added Eric Duminil @supercat also, do you have an example of non transitive ==? The only half surprising fact I could find is that == isn't reflective with NaN.!= cannot be transitive, and isn't supposed to be, is it?
Oct 22, 2020 at 5:42 comment added Eric Duminil @supercat as far as I can tell, you're just proposing another kind of broken. There are different reasons for a number to be NaN, but the reason isn't saved in the object. So you really cannot assume NaN==NaN, because that could mean 0/0==sqrt(-1).
Oct 21, 2020 at 16:47 comment added supercat Unfortunately, programming languages nowadays are expected to define == and != in a broken non-transitive fashion for floating-point types, rather than specifying e.g. that if x and y are both NaN, x==y, x>=y, and x<=y will be true (and other comparisons false), and if x is NaN and Y isn't or vice versa, x!=y will be true and all other comparisons false. That would have allowed testing for NaN via !(x>=0 || x<=0), while keeping == as an equivalence relation.
Oct 20, 2020 at 22:09 comment added Brie I was unnecessarily specific - this is really only tangentially financial-related; see edits. Your points are well-taken.
Oct 20, 2020 at 21:30 history answered Caleth CC BY-SA 4.0