[HN Gopher] How does your programming language handle "minus zer...
       ___________________________________________________________________
        
       How does your programming language handle "minus zero" (-0.0)?
        
       Author : ibobev
       Score  : 111 points
       Date   : 2021-03-05 10:29 UTC (12 hours ago)
        
 (HTM) web link (lemire.me)
 (TXT) w3m dump (lemire.me)
        
       | kaladin_1 wrote:
       | Elixir does not distinguish signs in zero, 0.
       | 
       | Therefore; -0.0 + 2.0 = 2.0 and 0.0 + 2.0 = 2.0
        
         | kzemek wrote:
         | Isn't that true for all correct implementations of negative
         | zero? It's still a neutral for addition
        
           | worc3131 wrote:
           | Not quite neutral. You return -0.0 only when needed.
           | >>> 0.0+0.0       0.0       >>> 0.0+(-0.0)       0.0
           | >>> (-0.0)+0.0       0.0       >>> (-0.0)+(-0.0)       -0.0
        
             | shultays wrote:
             | heh, looks like abs(-0.0) is slightly less than abs(+0.0)!
        
             | thaumasiotes wrote:
             | > Not quite neutral.
             | 
             | Hmm? Your examples show -0.0 being additively neutral in
             | every case. +0.0 is the one that behaves weirdly.
        
         | chrisseaton wrote:
         | I don't understand what you think a result could look like here
         | that does distinguish the sign? What are you expecting? -2.0?
         | That doesn't make any sense. 2.0 is the correct answer under
         | all circumstances as far as I can see.
        
         | mcintyre1994 wrote:
         | I think you're right that they're indistinguishable, in that
         | -0.0 == 0.0
         | 
         | The division by 0 in that article gives the same
         | ArithmeticError in each case, notice the 0.0 in both errors:
         | iex(8)> 1.0 / -0.0         ** (ArithmeticError) bad argument in
         | arithmetic expression: 1.0 / 0.0             :erlang./(1.0,
         | 0.0)         iex(8)> 1.0/0.0         ** (ArithmeticError) bad
         | argument in arithmetic expression: 1.0 / 0.0
         | :erlang./(1.0, 0.0)
         | 
         | It's also ignored when rounding:                   iex(10)>
         | Float.round(-0.01, 1)         0.0         iex(11)>
         | Float.round(0.01, 1)         0.0
        
       | The_rationalist wrote:
       | I was just thinking about this 2 days ago, the coincidence!
        
       | johndoe42377 wrote:
       | Since definition of zero is _x - x_ , negative zero is utter
       | bullshit.
        
       | SloopJon wrote:
       | It's also worth understanding whether +0.0 and -0.0 are
       | equivalent in your environment:
       | 
       | * Do they compare equal?
       | 
       | * If they're convertible to boolean, do they both evaluate to
       | false?
       | 
       | * If you serialize/deserialize the value (e.g., to JSON and
       | back), does it maintain the distinction?
       | 
       | * If you send this value to a database (esp. one with stored
       | procedures), how does its behavior compare to your language?
        
       | sesutton wrote:
       | Interestingly Go will give you a negative 0 if you use
       | strconv.ParseFloat("-0.0", 64) but I can't see any way to get
       | -0.0 from a number literal.
        
         | jeffbee wrote:
         | You can't get a negative zero with a constant declaration, nor
         | can you get NaN, infinity. These are documented language facts.
         | 
         | """Numeric constants represent exact values of arbitrary
         | precision and do not overflow. Consequently, there are no
         | constants denoting the IEEE-754 negative zero, infinity, and
         | not-a-number values."""
        
       | retrac wrote:
       | As an aside, historically many of the early binary computers used
       | ones complement. So they had both -0 and +0 integers as well.
       | While ones complement is probably more obvious than twos
       | complement, it was near-universally considered a terrible mistake
       | by the mid-1960s, and everything of note since has been twos
       | complement.
       | 
       | It didn't die quickly though. The UNIVAC is still with us (in
       | emulation) and that is likely the reason why the C standard
       | addresses the question of negative zero integers. (Their handling
       | is implementation specific, of course.)
        
       | dnautics wrote:
       | the Erlang VM said "screw IEEE":                   iex(1)> -0.0
       | === 0.0         true
       | 
       | there's also explicitly no infinity or NaN, there is a software
       | throw for all (core) implemented function domain failures.
       | 
       | This has, however, recently come up for Nx (numerical elixir)
       | which had to implement and standardize ways to shim these IEEE
       | concepts back into the VM for interop purposes.
        
         | recursive wrote:
         | Is there any language that treats the zeros as unequal? That
         | would seem like the real "screw IEEE".
        
           | dnautics wrote:
           | in the specific case of erlang, and the erlang beam vms,
           | 
           | 0 !== 0.0
           | 
           | Of course 0 == 0.0
           | 
           | I imagine if they had chosen to follow IEEE, it would have
           | been that 0.0 !== -0.0 and 0.0 == 0.0.
        
             | recursive wrote:
             | I don't know erlang, but it looks to me like that's a
             | difference between types. (integer vs float)
             | 
             | Is there a language that treats different float values of
             | zero as unequal? That would be surprising to me. And
             | possibly silly.
        
       | sir_nop wrote:
       | There are still (a few) computers in the world (Sperry Univac
       | legacy support) using one's complement arithmetic, hence having a
       | positive and negative zero in the architecture.
       | 
       | https://en.wikipedia.org/wiki/Ones%27_complement
        
         | quelsolaar wrote:
         | Well all computers supporting IEEE 754 floating point numbers
         | have a positive and a negative 0. Thats quite a few.
         | 
         | I prefer to store all my most important data in the sign bit of
         | floats set to zero.
        
           | faeyanpiraat wrote:
           | Why?
           | 
           | Isn't that what bool is for?
        
             | cbsks wrote:
             | You missed the invisible sarcasm tag
        
             | [deleted]
        
           | quelsolaar wrote:
           | Its also the key to solving this:
           | 
           | How is the result of:
           | 
           | a _= 0;
           | 
           | different from:
           | 
           | a _= -0;
           | 
           | :-)
        
       | robert-brown wrote:
       | Common Lisp handles negative zero quite well.
        
       | croes wrote:
       | The inverse of zero is infinity? Shouldn't it be undefined?
        
         | marcosdumay wrote:
         | Floating point numbers represent the extended real set, where
         | infinity exists. What is completely different from the integral
         | numbers most computers use, on those division by zero is
         | undefined.
        
           | thaumasiotes wrote:
           | Division by zero is still undefined in the extended reals. To
           | define it you'd need something like the projective reals. But
           | it doesn't matter; floating point numbers don't have a zero;
           | they have two zeroes of different signs.
        
         | Igelau wrote:
         | Floating point is a real trip. They should probably spend more
         | time going over its intricacies in programming courses, because
         | its not going anywhere.
         | 
         | E.g. you should hardly ever test floating point numbers for
         | equality. Instead you usually check if they are "close enough"
         | within an expected precision.
        
         | banachtarski wrote:
         | The limit of a function 1/x as x approaches zero from the left
         | or right is well defined as negative or positive infinity
         | respectively. The limit is only undefined when no approach
         | direction is specified (as the results from the left and right
         | do not agree)
        
         | thaumasiotes wrote:
         | Not if you know that it's positive or negative. The inverse of
         | a negative infinitesimal can't be anything other than a
         | negative infinite number, and the inverse of a positive
         | infinitesimal can't be anything other than a positive infinite
         | number. There's no difficulty with the definitions.
        
           | ben509 wrote:
           | There is the difficulty that you don't actually have zero,
           | you have postive and negative infinitesimal.
        
             | thaumasiotes wrote:
             | That is the meaning of "+0.0" and "-0.0". Actual zero is
             | neither.
        
         | recursive wrote:
         | Not if you're following IEEE-754.
        
       | TorKlingberg wrote:
       | I feel like floating point is a completely separate branch of
       | programming that a lot of coders never use. When they do it's
       | often a mistake, like for currency. Yet floating point is very
       | useful for scientific calculations and simulations, which is what
       | computers were all about for the first couple of decades.
       | 
       | I have a suspicion that on a fundamental level, floating point
       | isn't actually good for games or machine learning. They're just
       | used because existing computers are so good at floating point
       | number crunching, especially GPUs.
        
         | civilized wrote:
         | Floats are essential for machine learning, scientific
         | computing, and any other application where the goal is to model
         | mathematical processes involving real numbers. The idea that
         | there is something out there that could do the job better than
         | floats is almost certainly wrong.
         | 
         | I'm fascinated by how common it is for programmers to hate
         | floats. Yes, if you write business software for a living you
         | may not have much use for them. But there's a lot more to
         | computing than business software.
        
           | amelius wrote:
           | > Floats are essential for
           | 
           | Not necessarily true. Theoretically you can replace floats by
           | fixed-point representations given enough bits, and in
           | practice this also works often.
           | 
           | It's a pity languages/hardware don't have good built-in
           | support for fixed-point numbers though.
        
             | lostcolony wrote:
             | Well, as mentioned elsewhere, because of historical
             | purposes, GPUs tend to optimize floating point operations
             | really heavily. Whereas bigint style things likely don't
             | benefit, in part because there's no "standard" for them at
             | that low a level. So it seems to me to be a bit of chicken
             | and egg; low level languages don't have them as part of the
             | standard, so graphic cards can't universally optimize for
             | them, and since graphic cards don't support optimizations
             | for them, there isn't anyone clamoring for it.
        
             | hctaw wrote:
             | Fixed point is obsolete on the vast majority of compute
             | devices today. It is only a reasonable alternative in ultra
             | low power scenarios or on tech stacks that haven't migrated
             | to modern architectures, like some DSPs (which are also
             | really only applicable in ultra low power devices).
             | 
             | On modern CPUs, fixed point is slower and error prone (both
             | in usage and the computations themselves) relative to
             | floating point.
             | 
             | I don't think it's a pity that fixed point support is out
             | the door. It sucks. Floats minus subnormals are the least
             | surprising numerical representation out there, and the most
             | versatile.
             | 
             | Do you really want to worry about whether your numbers are
             | saturating or wrapping around? Keeping track of what your
             | max/min are? Tracking decimal places? Implementing division
             | by hand? Screw all that. Fixed point is awful and is
             | essentially an academic exercise today.
        
             | civilized wrote:
             | Okay, so now, relative to floating point arithmetic, you've
             | sacrificed an enormous amount of dynamic range and have to
             | worry about overflow and underflow much more than before.
             | 
             | What did you gain from this, exactly?
             | 
             | I'm sure there are some special situations where fixed
             | point is better, but for general purpose scientific and
             | technical computing, floating point is obviously the right
             | choice.
        
               | [deleted]
        
               | hctaw wrote:
               | On some low power architectures without FPUs it is
               | significantly more power/compute efficient to use fixed
               | point arithmetic. But that's really it.
        
           | abraae wrote:
           | For some reason many programmers love to hate technologies
           | that are old.
           | 
           | Hate floats, love big decimals
           | 
           | Hate OOP, love functional
           | 
           | Hate RDBMS, love nosql
           | 
           | Hate html web pages, love SPA
           | 
           | In my opinion it's a confluence of influences.
           | 
           | 1) the same social media attitudes poisoning society
           | generally. "I've got an opinion, and it's worth just as much
           | as yours". News flash - opinions are like arseholes, everyone
           | has one.
           | 
           | 2) Inexperience - devs who have only ever built chat apps and
           | don't understand why relationships hence RDBMS are common and
           | useful in line of business applications. Devs who have not
           | tried to capture the water level in a tank or the voltage
           | from a solar panel and don't get why floats are useful.
           | 
           | 3) resume padding. nuff said
        
             | andrewflnr wrote:
             | Not disputing your other points, but functional programming
             | is by most measures older than OOP. The FP hype now is
             | definitely more a matter of rediscovering the wisdom of the
             | past, and I think that's a good thing.
        
               | abraae wrote:
               | That's an excellent point.
               | 
               | Although to go down that road, schemaless databases
               | preceded RDBMS by decades, and then were replaced for
               | good reasons.
        
         | kingkonz1 wrote:
         | What better alternative is there for handling currencies?
         | Multiplying the original amount by 100 and casting to an int?
         | ($3.50 -> 350)?
        
         | legulere wrote:
         | One example where floating point does not match the problem
         | field is GIS. Coordinates are bound by the earth's
         | circumference. Fixed point would make much more sense, but
         | neither hardware nor software support is there.
        
           | lylecheatham wrote:
           | I mean most GIS software is pretty aware of precision models.
           | Take GEOS for example, it's got a variety of ways to specify
           | the precision in number of decimal places for a geometry. It
           | still uses doubles underneath, but that's to avoid unneeded
           | code complexity.
        
         | emiliobumachar wrote:
         | > very useful for scientific calculations and simulations
         | 
         | Don't forget control systems.
        
         | PaulHoule wrote:
         | It is the opposite.
         | 
         | From Microsoft BASIC to Javascript, many programmers have
         | worked in languages that only have floats. Financial
         | calculations involve exponential/log math much like scientific
         | problems. There are issues with rounding and representation
         | there (e.g. there is no such thing as $0.01 in floating point,
         | only $0.50, $0.25, $0.125 and some sum of 1/2 fractions that
         | comes very close to $0.01 and even reads in and writes out as
         | $0.01 even though it isn't.)
        
         | TacticalCoder wrote:
         | > When they do it's often a mistake, like for currency.
         | 
         | The most beautiful FP bug I remember was a denial of service in
         | some webservers where by setting the header "Accepted Language:
         | en-gb;q=0.3 en;q=0.8 ..." to a specific value you could send
         | the official Java floating-point parser in an infinite loop
         | (and this affected several Java webservers).
         | 
         | So at each webpage request, you were sending one CPU core of
         | the webserver basically busy-looping. Hence crashing the
         | webserver in a few requests at most.
         | 
         | Now it'd be heresy if I were to say that maybe, just maybe, had
         | the standards mandated to use 0 to 100 for weighting instead of
         | 0 to 1.0 we could have dodged a whole source of potential
         | issues!?
         | 
         | No, no, I realize this is heresy: let's all keep using numbers
         | that cannot even be represented correctly (except as strings),
         | parse those strings into something approximately representing
         | what's written in the string, then make more approximation
         | errors while doing computation with these numbers, propagation
         | errors, epsilon estimation errors, and keep insisting we all
         | could have authored "What every computer scientist should known
         | about floating-point numbers" (which is 80 pages long and,
         | well, approaching a treaty) ; )
         | 
         | /rant off
        
           | kevin_thibedeau wrote:
           | Don't blame the protocol, blame the language. Nothing
           | prevents the use of fixed point for such numbers. It's just
           | the Java ecosystem and the weakness of languages that use
           | pervasive exceptions to the point that nobody can keep track
           | of them all that is the cause of such issues.
        
             | toast0 wrote:
             | > Don't blame the protocol, blame the language. Nothing
             | prevents the use of fixed point for such numbers.
             | 
             | I absolutely blame the protocol. Fixed point isn't widely
             | available and used, but integers are. Someone below says
             | protocol spec goes to three digits past the decimal. Using
             | a constrained integer would have allowed the same range of
             | values, but without the complexity of decimal numbers;
             | that's a protocol mistake.
             | 
             | In addition to the ease of using floating point numbers to
             | incorrectly represent decimals, there's also fun with
             | formatting, comma vs period, number of digits to report,
             | etc.
        
           | strictfp wrote:
           | Meh, it's not like there can't be a bug in whatever other
           | parsing code a webserver uses.
           | 
           | Maybe using a float is overkill in this case, since you're
           | never going to hit more than a hundred languages. But it's at
           | least not setting any limitations.
        
             | lostcolony wrote:
             | Based on the OP, this was the official parser for floats.
             | That's a bit more extravagant of a bug.
             | 
             | I also would invite you to find a similar instance where a
             | parsing bug for integers crashes the server. Not throws an
             | exception, but falls over in an uncatchable way. I'm not
             | sure I have ever seen one.
        
             | duckerude wrote:
             | No, it is setting limitations, they're just harder to
             | understand and predict. Here's what the RFC says:
             | qvalue         = ( "0" [ "." 0*3DIGIT ] )
             | | ( "1" [ "." 0*3("0") ] )
             | 
             | (https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec
             | 3....)
             | 
             | There are 1001 valid values with 1117 representations. Only
             | in practice, Firefox clamps to 2 decimal places, and it
             | used to clamp to 1 decimal place
             | (https://bugzilla.mozilla.org/show_bug.cgi?id=672448), and
             | who knows what other software does.
             | 
             | And it gets worse: the grandparent suggests there are
             | servers that parse it as floating point. Do they accept
             | q=1e2? If they accept it, are there clients that send it?
             | Do you need to be compatible with those clients?
        
             | mattgreenrocks wrote:
             | The issue is that the representation of floating point
             | numbers imposes additional cognitive burden that the code
             | must handle. How does the web server header parsing code
             | handle positive/negative infinity? How about NaN?
             | 
             | NaNs/infs are particularly vicious, as they propagate
             | through computations.
        
           | Someone wrote:
           | Probably https://www.exploringbinary.com/java-hangs-when-
           | converting-2...: _"Java -- both its runtime and compiler --
           | go into an infinite loop when converting the decimal number
           | 2.2250738585072012e-308 to double-precision binary floating-
           | point. This number is supposed to convert to 0x1p-1022, which
           | is DBL_MIN; instead, Java gets stuck, oscillating between
           | 0x1p-1022 and 0x0.fffffffffffffp-1022, the largest subnormal
           | double-precision floating-point number."_
        
           | throwaway8581 wrote:
           | There is nothing wrong with the protocol. The protocol has
           | _nothing_ to do with what representation is used by software
           | that speaks the protocol. Software could just as well parse
           | those values as integers. Just drop the decimal point and pad
           | with zeroes. Or use a decimal type (but there is really no
           | need to).
        
             | duckerude wrote:
             | Assigning blame is a bit academic.
             | 
             | I think a protocol that used integers instead of decimal
             | point would have led to more correct implementations. So it
             | would be a better protocol.
        
             | 8note wrote:
             | The protocol has an obvious implementation choice and some
             | non-obvious alternatives.
             | 
             | If the protocol had nothing to do with it, I don't think
             | you'd see the same bug come up in as many implementations
        
               | [deleted]
        
         | oivey wrote:
         | Lots of the math in games and ML assumes you're operating in
         | the reals. For example, the optimization in neural networks.
         | Integers and fixed point won't work.
        
           | bwestergard wrote:
           | Floats have a totally different algebra than the reals,
           | though.
        
             | adwn wrote:
             | Only in the strictly mathematical sense. To a first
             | approximation, floating-point numbers behave like real
             | numbers, and that's good enough for many use-cases (not
             | all, though).
             | 
             | Similarly, fixed-width integers have a totally different
             | algebra than true integers, and yet they're immensely
             | useful.
        
               | bwestergard wrote:
               | "To a first approximation, floating-point numbers behave
               | like real numbers"
               | 
               | This is incorrect. To count as an approximation, there
               | have to be some accuracy bounds. This is impossible to
               | define, as the reals don't have the same cardinality as
               | any floating point number system.
               | 
               | Now, for many interesting and useful real-valued
               | functions, a float-valued function can be defined that is
               | an approximation. But there is no general way to map a
               | function defined on the reals to a function defined on
               | the floats with a known accuracy.
        
               | legulere wrote:
               | fixed-width integers have exactly the same semantics as
               | true integers bar overflow, which is a very easy to
               | understand concept.
               | 
               | Floating-point numbers behave like a physicist would do
               | calculations rounding at every step, but doing everything
               | in binary. Or hexadecimal if you prefer, it's equivalent,
               | but still difficult to get your head around to. Then
               | there additionally is + and - 0 and + and - infinity, and
               | several settings for how rounding is done exactly.
        
             | oivey wrote:
             | Yeah, but closer to the reals than fixed point or integers.
             | That's kind of the point of the standard.
        
           | sltkr wrote:
           | Doesn't ML work fine with fixed point numbers? I don't think
           | there is a particular use case for very large or very small
           | numbers.
        
             | sharpneli wrote:
             | It's the exact opposite. It really loves large and small
             | numbers, the precision of a number doesn't matter that much
             | 
             | That's the reason why they introduced
             | https://en.wikipedia.org/wiki/Bfloat16_floating-
             | point_format
             | 
             | It's similar to normal half precision float but the
             | exponent is the same as with 32bit float and mantissa has
             | been sacrificed to get room for it.
        
             | PeterisP wrote:
             | ML optimization algorithms generally _do_ require proper
             | handling of very,very small numbers for e.g. calculation of
             | gradients.
             | 
             | There's a bunch of work on discretization of models _after_
             | you 've done optimizing them - that works, you can get
             | high-performance inference with low-bit fixed point
             | numbers; but that's after the learning has been done using
             | proper floating point (however, you don't necessarily need
             | high accuracy floating point, e.g. single precision may
             | work betted than double precision simply because it's twice
             | less bytes to copy over).
        
             | oivey wrote:
             | Referring to ML is so vague that it's not particularly
             | meaningful. The answer in general is no. There's been some
             | work showing neural networks can function with low
             | precision floating point, but that's still pretty different
             | than fixed point.
        
         | linkdd wrote:
         | In some game engines, Fixed Point Arithmetic is used instead of
         | Floating Point, because it's faster, and the approximation is
         | generally good enough for a game.
        
           | quelsolaar wrote:
           | I dont think this is true. Integer math is used in some game
           | engines because they need to be deterministic, between
           | networked computers (and different CPUs rounds floating point
           | numbers differently). I have written an engine like that, and
           | i know that Starcraft 2 is all integer for the same reason.
           | No one does it because its faster or easier. Its a pain.
        
             | neurocline wrote:
             | Starcraft II uses floats, but for the game simulation
             | portion it uses an internal software floating-point library
             | to ensure consistency.
        
               | quelsolaar wrote:
               | You are right, all the graphics are full of floats.
               | Writing "all" was a bit of an overreach.
        
             | bjourne wrote:
             | Which modern general-purpose CPUs do not follow IEEE 754? I
             | don't think what you're saying is true.
        
               | quelsolaar wrote:
               | They all follow IEEE 754. But that defines the
               | representation of the bits in a floating point number,
               | not what happens when you operate on them. Different
               | implementations do rounding differently, and there are
               | arguments about how to do this correctly. There can be
               | multiple ways to represent the same number even (this is
               | a reason not to ever do a == compare on floating point
               | number that have been operated on). Not only have there
               | been differences between CPU makers, but also between
               | different CPU of the same vendor.
               | 
               | A separate, complicating factor is that floating point
               | math often don't yield the same results with different
               | levels of optimization turned on. The reason to use
               | integer math for games is because you want it to be
               | deterministic so can be an issue.
        
               | zokier wrote:
               | IEEE 754 does also specify operations and their behavior.
               | E.g. section 5.1 (from 2008 edition):
               | 
               | > All conforming implementations of this standard shall
               | provide the operations listed in this clause for all
               | supported arithmetic formats, except as stated below.
               | Each of the computational operations that return a
               | numeric result specified by this standard shall be
               | performed as if it first produced an intermediate result
               | correct to infinite precision and with unbounded range,
               | and then rounded that intermediate result, if necessary,
               | to fit in the destination's format (see 4 and 7).
        
               | quelsolaar wrote:
               | Well the fact is that different hardware rounds it
               | differently, so its the world we live in. My guess is
               | that actually implementing something in hardware " to
               | infinite precision and with unbounded range" might not be
               | realistic.
        
               | [deleted]
        
             | linkdd wrote:
             | I never said it was easier and I never said ALL game
             | engines.
             | 
             | And computing integers IS faster than computing floats, at
             | least on a CPU.
        
               | quelsolaar wrote:
               | >And computing integers IS faster than computing floats,
               | at least on a CPU.
               | 
               | In the abstract yes. In reality not so much. A lot of
               | what floats are used for in games is vector math (you are
               | often in a 2D/3D world), and vector math in fixed point
               | requires a lot more work in integer math since you
               | constantly need to shift down things in order to avoid
               | overflow. Overflow bugs are a constant problem when doing
               | dot products in fixed point integer math.
               | 
               | Another common operation in vector math is square root
               | (to normalize vectors) Modern CPU's do that very fast,
               | and you can also use clever approximations that use the
               | way floating point's are represented in hardware.
               | 
               | Most of whats done in 32 bit floats in games, needs to be
               | done with 64bit integers to manage these problems if you
               | decide to use integers, and that means that your data
               | grows, more cache misses, and things slow down.
               | 
               | On top of this everything you do in a game needs to be
               | drawn on the GPU so you need to convert everything to
               | floats anyway to show them on screen, and converting
               | between integers and floats is also slow.
        
               | linkdd wrote:
               | I never use the square root in games, I always compare
               | squared distances (since the properties are the same).
               | 
               | If you try to do with Fixed Point Arithmetic what was
               | intended to be done with Floating Point, you're the
               | problem.
               | 
               | A 32 bits integer can hold values up to 4 billions, if I
               | have that kind of value in a simple game, then yes i will
               | switch to Floating Point Arithmetic, but when does that
               | use case happen if you're not writing a physic simulation
               | game ?
        
               | edflsafoiewq wrote:
               | The biggest problem with fixed point is reciprocals
               | behave very poorly; ie. x*(1/x)=1 and 1/(1/x)=x fail very
               | badly. In order for these to work you obviously need the
               | same amount of numbers above 1 as below 1, like in
               | floating point.
               | 
               | Using fixed point with 11 bits after the decimal, with
               | numbers as low as 100 (18 bits) we already have errors as
               | large as 100*(1/100)=0.977.
        
               | quelsolaar wrote:
               | > A 32 bits integer can hold values up to 4 billions, if
               | I have that kind of value in a simple game, then yes i
               | will switch to Floating Point Arithmetic, but when does
               | that use case happen if you're not writing a physic
               | simulation game ?
               | 
               | All the time. Let me give you an example from a game I
               | made. During early R&D I used 32 bit numbers and a fixed
               | point of 11 bits. That means that a normalized vector is
               | between 1024 and -1023. You can do 2 dot products between
               | vectors before it breaks it breaks. (10 + 10 + 10 bits
               | plus one sign bit). That means that you have to do a lot
               | of shifting down. the world can only be 20 bits large,
               | because you need to be able to multiply world coordinates
               | with vectors without getting overflow.
               | 
               | 20 bis is very low resolution for a real-time world. You
               | get problems with things not being able to move slow
               | enough at high frame rates. (this was in 2D). Switching
               | to 64 bit was the right move.
        
               | adwn wrote:
               | It appears you have a very niche definition of "game",
               | one which excludes basically all 3D games.
        
               | linkdd wrote:
               | Yes, that's exactly why I wrote:
               | 
               | > some game engines
               | 
               | and
               | 
               | > simple games
               | 
               | A 3D game is not a simple game.
        
               | adwn wrote:
               | Ugh, do you _really_ have to be this nitpicky? Fine, you
               | wrote:
               | 
               | > _the approximation is generally good enough for a game_
               | 
               | No, it's not _generally_ good enough for a game - only
               | for _some_ games, and not good enough for _any_ game with
               | 3D graphics.
        
               | Qwertious wrote:
               | Speaking of nitpicky, I thought the gamecube's GPU was
               | integer-driven? And it has plenty of 3D games.
        
             | sandworm101 wrote:
             | It depends on which 0 you are talking about. The 1-1=0 or
             | the 1/infinity zero. Somewhere deep in a physics department
             | there is an equation where the distinction either confirms
             | or denies the multiverse.
        
               | justincredible wrote:
               | 1/infinity is not 0, it's infinitesimal.
        
           | maximilianburke wrote:
           | It might be a little faster for addition and subtraction in
           | synthetic benchmarks -- and with the use of pipelining might
           | end up being slower overall -- but multiplication and
           | division are considerably faster with floating point.
        
             | dnautics wrote:
             | division, yes, but multiplication is faster, but it's not
             | huge. The limiting factor for multiplication is that it's
             | O(N^2) in multiplied digits; so a 32-bit fixed point has
             | 32x32 and IEEE fp32 multiplication has 23x23.
        
               | krackers wrote:
               | That's assuming that you're implementing multiplication
               | in software though, right? Since CPUs have dedicated
               | multipliers, aren't both around a single cycle?
        
               | dnautics wrote:
               | They are not in general (iirc 64b mult is down to 3
               | cycles now), but usually in an x86 cpu it can run
               | microinstructions out of order enough so that the
               | multiplication looks like it's finished in one cycle.
        
         | quelsolaar wrote:
         | As someone who has started out making games on Playstation 1
         | that didn't have floating point hardware, I can with authority
         | say that developing games with only integers suck. Floating
         | point number are far easier and robust to use.
        
           | pfraze wrote:
           | Only integers? Wow. Were int pairs used to represent numbers
           | with decimals or what?
        
             | coopierez wrote:
             | The GPU made use of fixed point numbers. So you have a set
             | number of decimal places for a number.
        
             | salicideblock wrote:
             | In signal processing on constrained domains (constrained
             | including the lack of an FPU), the usual alternative to
             | floating point is "fixed point" arithmethic.
             | 
             | Basically you use the platform's native types (e.g. uint32)
             | and decide which of the bits are for the integer part and
             | which are for the fractional. uint32 can be interpreted as
             | 20/12 for example. Your register went from representing
             | "units" to representing "2^-12 increments of an unit". The
             | ALU can do sum/comparison/subtractions transparently, but
             | multiplications and (god forbid) divisions require shifting
             | to return to the original representation.
             | 
             | The choice of how to split the bits is a tradeoff between
             | range and precision. It can vary from one routine to
             | another. It's a pain to compose code with it.
             | 
             | Short story: native float types are a blessing for
             | programmer productivity and library interoperability.
        
               | okl wrote:
               | The Wikipedia page explains the operations:
               | https://en.wikipedia.org/wiki/Q_(number_format)
        
             | linkdd wrote:
             | Let's say you have two 4 bits integer to form an 8 bit
             | decimal number:
             | 
             | 1111.1111 is (1 + 2 + 4 + 8) + (1/2 + 1/4 + 1/8 + 1/16)
        
             | timerol wrote:
             | To use only integers, you generally try to express all
             | numbers in units of the smallest quantity. So any money is
             | in integer cents, any distance is in integer (spatial
             | resolution size). It gets annoying with derived units: Time
             | can be stored in integer frames, but then you'll need a
             | rational type of some kind to properly handle velocity. Or
             | you just round to the nearest (spatial resolution) per
             | frame and hope the errors don't look too weird on the other
             | side.
        
           | ajuc wrote:
           | Did you use macros/operator overloading for all that bit
           | shifting or just hardcoded it everywhere?
           | 
           | We made a simple 3d demo for uni using fixed math (and we
           | were clueless then and weren't using macros because sometimes
           | you could refactor some operations out that way and we wanted
           | all the speed). There were lots of bugs caused by this.
           | 
           | Can't imagine how painful writing a whole game this way would
           | be.
        
           | scrooched_moose wrote:
           | Isn't that what caused the PS1 graphics "wobble"? I remember
           | you could just stare at a wall, rotate the camera, and the
           | textures would slightly jitter and move. It's really obvious
           | in some the Metal Gear cutscenes, especially this
           | conversation with Donald Anderson where the camera pans up
           | from the floor (at 15m) or the sweep(15m31s):
           | 
           | https://www.youtube.com/watch?v=VLTqIXZ1jQQ#t=15m00s
           | 
           | I never had a PS1 but it always bugged me when playing on
           | someone elses.
        
             | codetrotter wrote:
             | > I never had a PS1 but it always bugged me when playing on
             | someone elses.
             | 
             | Conversely I like the fact a lot that it does. And some
             | others that probably have fond memories of PS1 too
             | recreated this on modern computers using shaders.
             | 
             | https://github.com/dsoft20/psx_retroshader
        
             | coopierez wrote:
             | This is because of two things: the affine texture mapping
             | was incorrect, and there was no sub-pixel precision. The
             | sub-pixel part is kinda float-related (though you could
             | make use of fixed point too).
        
             | quelsolaar wrote:
             | yes, and the PS1 had a vector unit built in to the CPU that
             | was used for world transform and it was only 24 bits.
             | 
             | Early PS1 games fit the entire world in to a 24 bit space,
             | and you can tell that there is steping if you drive very
             | slow in a game like Ridge Racer. Later games moved the
             | world around in the coordinate system to manage precision.
             | 
             | Another reason why the graphics looks extra "popy" on PS1
             | (And early DirectX games) is that vertices where computed
             | at a pixel accuracy. OpenGL, Doom, Quake and more modern
             | hardware have sub pixel accuracy.
        
             | edflsafoiewq wrote:
             | No. The DS uses only fixed point numbers and does not
             | wobble.
        
       | tomkaos wrote:
       | Does -0.0 == +0.0 ?
        
         | FartyMcFarter wrote:
         | Yes, at least in C++: https://godbolt.org/z/afqYbE
         | 
         | Its bitwise representation is different, but when compared as
         | floats they are equal.
        
         | The_rationalist wrote:
         | It does
        
       | d3nj4l wrote:
       | Ruby seems to handle this correctly:                   >> 1 /
       | -0.0         => -Infinity
       | 
       | Although you have to put the 0.0, otherwise it treats it as an
       | integer and makes it 0.
        
         | fortran77 wrote:
         | Dividing by zero is "undefined" not "Infinity" because there is
         | not a "well defined limit."
         | 
         | https://en.wikipedia.org/wiki/Division_by_zero
        
           | d3nj4l wrote:
           | From the article you link:
           | 
           | > Depending on the programming environment and the type of
           | number (e.g. floating point, integer) being divided by zero,
           | it may generate positive or negative infinity by the IEEE 754
           | floating point standard.
        
         | darig wrote:
         | Shouldn't the answer be NaN or an illegal division by 0 fatal
         | error/exception?
        
       | bendiksolheim wrote:
       | Does anyone have a good example of a programming problem where we
       | _need_ signed zero? Or where it makes things significantly
       | simpler? As far as I know, there is no distinction between -0 and
       | +0 in math, so I have never really understood why this is a thing
       | in computers.
        
         | bombcar wrote:
         | Amusingly enough the Apple Watch reports temperature as 0deg
         | and sometimes as -0deg, I've not determined what causes that,
         | perhaps rounding around 0?
        
           | sly010 wrote:
           | Maybe the actual temperature value has a few more digits that
           | are truncated during formatting: "-0.001" -> "-0"
        
           | portmanteaufu wrote:
           | Sometimes the sign is used to indicate which "direction" the
           | temperature is moving. If it was -10deg overnight and it's
           | -0deg now, the puddles outside will still be frozen. If it
           | was 10deg overnight and it's 0deg now, the puddles will still
           | be liquid.
           | 
           | (Edit: no idea whether this applies to the Apple watch, it's
           | just a use case for -0 with regards to temperature.)
        
             | majewsky wrote:
             | Your predictions about the state of the puddle are most
             | likely right, but not for the reasons that you think.
             | 
             | Air temperature is commonly measured at 2m above ground. An
             | measurement of 0deg air temperature does not imply 0deg
             | ground temperature. The more significant effect is that the
             | ground has a higher thermal capacity than the air, so it
             | changes temperature more slowly throughout the day. If it's
             | been colder before and now it's 0deg, the ground is still
             | way below 0deg and thus puddles are frozen. If it was
             | warmer and now the air has cooled down to 0deg, the ground
             | is going to be a bit warmer still and thus puddles are
             | liquid.
             | 
             | Denoting this difference as +0deg and -0deg does not seem
             | very useful since the same effect is going to be nearly
             | equally significant at 1deg or -2deg.
             | 
             | (Sidenote: The thermal capacity of the ground is also the
             | reason why air temperature is not measured anywhere near
             | the ground.)
        
               | bombcar wrote:
               | The thermal capacity of the ground is also why, if you're
               | insulating a basement or slab, you want to insulate the
               | edges and DOWN - but you don't need to insulate in the
               | center of the slab (as eventually the ground reaches the
               | ambient temperature and acts as a huge thermal mass).
        
           | majewsky wrote:
           | Probably not even rounding, but just printf. The following
           | works on my zsh:                 $ printf '%.0fdeg\n' 0.3
           | 0deg       $ printf '%.0fdeg\n' -0.3       -0deg
        
             | a1369209993 wrote:
             | That actually _is_ rounding around zero (to zero decimal
             | places, but it is rounding).
        
           | netzone wrote:
           | I believe that's actually a standard presentation, I've seen
           | it in several weather graphs. It's basically a rounding yeah,
           | signifying it's just slightly below zero, but not enough to
           | round to -1deg.
        
         | patrec wrote:
         | When does this need arise? Well, otherwise inverting a value
         | can change it's sign and in particular inverting -[?] twice
         | will give you +[?], and being off by "2[?]" is a pretty large
         | error for a lot of computations ;)
         | 
         | You can end up with zeros and infinities pretty easily because
         | you overflow or underflow the range of floating point
         | precision, and generally you want something sensible to happen
         | in typical cases, even if some common arithmetic identities
         | necessarily break down.
         | 
         | I would actually like a true signed zero (or rather "epsilon"
         | value ), so -0 _and_ +0 as distinct from  "normal" 0 which is
         | truly unsigned, neither positive nor negative. The former two
         | would only arise from underflow, and the reason this is useful
         | that if you underflow from below zero and invert that you want
         | to get -[?] and if you underflow from above zero and invert
         | that you want to get +[?]. Inverting a signless zero should
         | give NaN (instead it gives +[?], which is nonsense in basically
         | any case where the domain is not inherently the non-negative
         | reals already and the 0 did not come about by and underflow; in
         | particular 1/0 should be NaN).
         | 
         | If anyone knows why this design was not chosen and what
         | fundamental downsides it has, I'd love to hear it. Obviously
         | representing three zeros is a tad more annoying, but IEEE754
         | has a lot of stuff that's annoying implementation wise but was
         | added for nicer numerical behavior (e.g. denormals, and of
         | course various "global" rounding modes etc. which probably
         | qualify as a mistake in retrospect).
        
           | Const-me wrote:
           | > If anyone knows why this design was not chosen and what
           | fundamental downsides it has, I'd love to hear it.
           | 
           | No fundamental ones, but a few practical.
           | 
           | 32-bit numbers have 2^32 unique values, the number is even.
           | Your approach makes the range asymmetrical like it happens
           | with integers.
           | 
           | The range for 8-bit signed integers is [ -128 .. +127 ]. On
           | ARM NEON there're two versions of integer negate and absolute
           | instructions, some (like vqnegq_s8 or vqabsq_s8) do
           | saturation i.e. transform -128 into +127, others (vnegq_s8,
           | vabsq_s8) don't change -128. Neither of them is particularly
           | good: the saturated version violates -(-x) == x, non-
           | saturated version violates abs(x)>=0. Same applies to the
           | rest of the signed integers (16, 32, 64 bits), an all modern
           | platforms.
           | 
           | With IEEE floats the range is symmetrical and none of that is
           | needed. Moreover, PCs don't have absolute or negate
           | instructions, but they instead have bitwise instructions
           | processing floats, like andps, orps, xorps, andnps, they
           | allow to flip, clear or set just the sign bit, very fast.
           | 
           | Another useful property of IEEE representation is that for
           | two intervals [ 0 .. FLT_MAX ] and [-FLT_MAX .. -0.0f ] sort
           | order of floats corresponds to [inverted] sort order of
           | 32-bit integers.
        
             | bluecalm wrote:
             | I wonder if it would be useful to have a signed integer
             | that has symmetric range and the one that is left is used
             | as NaN. Overflows would set it to NaN for example. Then
             | again, once that's on the table it's very tempting to steal
             | two more values for +/- inf. I think it's very useful to
             | have full range unsigned ints but signed ones could have
             | range reduced to make them less error prone.
        
             | patrec wrote:
             | > Your approach makes the range asymmetrical like it
             | happens with integers.
             | 
             | Not necessarily since you've got (a lot of different) NaNs
             | anyway. For the sake of argument, you could give up one one
             | of them and make it positive zero (since this
             | representation would be unnatural, it would slow stuff
             | down, just as non-finite values do on many CPUs. Wouldn't
             | matter that much since signed zeros would only arise from
             | underflow).
             | 
             | > Another useful property of IEEE representation is that
             | for two intervals [ 0 .. FLT_MAX ] and [-FLT_MAX .. -0.0f ]
             | sort order of floats corresponds to [inverted] sort order
             | of 32-bit integers.
             | 
             | I'm aware, but as you correctly note this only works in the
             | right direction for unsigned values. And it's just not that
             | important a benefit, I'd _much_ rather have my calculations
             | come out right than being able to sort positive floating
             | point numbers with an integer sort routine.
        
           | amelius wrote:
           | [?] is not a number. Using it as a number is a hack invented
           | by mathematicians.
        
             | analog31 wrote:
             | That's right. It's a symbol. When you see it in an
             | expression, you're probably expected to interpret it in
             | light of a limit of some kind. It's just convenient to
             | write it into an expression rather than use cumbersome
             | limit notation all over the place.
             | 
             | Like many notational shortcuts, it's a hack supported by
             | proof. ;-)
        
               | taeric wrote:
               | This explanation feels off, to me. Aren't all numbers
               | symbols? Pi, e, 10, 0xA, 9.99999...?
        
               | analog31 wrote:
               | In my view, numbers are numbers, and symbols are symbols.
               | There's an agreement that a symbol _represents_ a number,
               | but there 's not a one-to-one relationship between
               | available symbols and available numbers. Normally this
               | isn't a problem, and we treat them interchangeably. And
               | indeed the distinction may only be a philosophical oddity
               | or a matter for mathematicians. But I believe nonetheless
               | that there is a distinction.
               | 
               | Now I was merely an undergrad math major, which means I
               | topped out before learning this stuff in a formal way.
               | But at my primitive level of understanding, I think of a
               | number as something that _behaves_ like a number within a
               | given system. What I learned in my courses was how
               | different kinds of numbers behaved: Whole numbers, reals,
               | complex, vectors and tensors, etc. I remember reading a
               | definition of  "tensor" that was to the effect of: A
               | tensor is something that behaves like a tensor, meaning
               | that the important thing is the behavior.
               | 
               | Another post in this page expressed that we should be
               | particularly cautious when dealing with numbers, symbols,
               | and IEEE floats, notably to beware that IEEE floats and
               | real numbers don't always behave the same. That was
               | treated in one of my math courses, "Numerical Analysis."
               | You could also get CS credit for that course, suggesting
               | its practical importance.
        
               | taeric wrote:
               | I think the consequences of what you are saying makes
               | sense. Would be neat to explore more of the idea. I was
               | starting to find, recently, that it was better to think
               | of numbers as symbols that follow operational rules. This
               | view seems counter to that.
        
               | analog31 wrote:
               | There is a view that math is "just" symbol manipulation.
               | So I can't say your approach is wrong. Probably whatever
               | works, works.
               | 
               | And you can usefully say things like "x is a number"
               | without saying which particular number x is.
        
               | gefh wrote:
               | But not all symbols are numbers.
        
               | taeric wrote:
               | Why not? One of the profound effects of computers is that
               | we have moved computing to be able to work with images.
               | Sounds. Etc.
               | 
               | I get that not all have simple algebraic concepts.
               | 
               | I get the impression I'm corrupting parts of I am a
               | Strange Loop? Would love to read more on this.
        
               | bjourne wrote:
               | Yes, in a way. What distinguishes irrational numbers from
               | rational numbers is that all rational numbers can be
               | represented by strings drawn from a regular language. For
               | example, all strings generated by the regular language
               | "-?\d+\\.\d+?_\d+" (where "_" denotes the repeating
               | decimal expansion as in 1/6 = 0.1_6) correspond to
               | exactly one rational number and all rational numbers
               | correspond to at least one string in this regular
               | language. Irrational numbers (and other types of
               | "numbers" such as +inf and -inf) cannot be represented by
               | any such regular language.
        
               | taeric wrote:
               | I'm not entirely sure I follow. Aren't pi and e
               | irrational numbers?
               | 
               | I also included .9_ as it is an easy trap to show we have
               | two ways of writing 1 in standard decimal notation.
               | 
               | Please read this whole post as a question. I'm genuinely
               | not clear on the distinction.
        
               | bjourne wrote:
               | Correct. Given the regular language I specified, each
               | rational has an infinite number of matching strings: 1.0
               | = 1.00 = 1.000 = 0.9_99 = 1.0_0 etc. The point is that
               | for every rational number you can think of, I can show
               | you at least one string in my regular language to
               | represent that number.
               | 
               | According to the finitists, this is a defining feature of
               | a "number". Since the same can't be done for irrational
               | numbers finitists conclude that irrational "numbers"
               | aren't numbers. You probably agree that all numbers are
               | (or can be represented by) symbols, but that not all
               | symbols are numbers. So how do we distinguish symbols
               | from numbers?
        
               | colejohnson66 wrote:
               | I was taught that you're supposed to read $y = \inf$ as:
               | y = lim_{x->\inf} x
               | 
               | Basically, $y$ isn't _necessarily_ infinity, but just a
               | number larger than you could ever write. The number at
               | the end of the number line if it existed.
        
             | steerablesafe wrote:
             | [?] is not used as a number by mathematicians. Maybe by
             | engineers.
        
               | chithanh wrote:
               | That is not entirely correct. Schmieden and Laugwitz for
               | example developed in the 1950s a nonstandard Analysis
               | which adjoins an infinitely large element (called O) to
               | the natural numbers. The basic idea was a formula A(O)
               | was true if A(n) was true for almost all finite natural
               | n.
               | 
               | While it wasn't immensely useful going forward, it helped
               | to clarify the use of infinity and infinitesimals in
               | earlier work.
        
               | steerablesafe wrote:
               | I'm well aware of nonstandard analysis, but [?] is still
               | not a number there, even though there are infinitely many
               | infinitely large elements .
        
               | Spivak wrote:
               | The extended complex plane is a space where inf is
               | actually number and where division by zero is allowed.
               | 
               | Same with the extended real line.
               | 
               | Infinity is as much a number as it is useful to define it
               | as such.
        
               | steerablesafe wrote:
               | Ah right, I forget that extending with a single infinity
               | element is useful with complex numbers and with geometry.
               | It's still not very common with the reals alone as +[?]
               | and -[?] are reasonable to want as separate elements
               | there, but it doesn't play nicely with 1/0 that way.
        
               | prionassembly wrote:
               | Ehh.
               | 
               | https://en.wikipedia.org/wiki/Extended_real_number_line
               | 
               | NB this is hardly nonstandard analysis.
        
           | jayd16 wrote:
           | So no then? As you say, epsilon should be used in this case.
        
             | patrec wrote:
             | I meant as in infinitesimal, not as in machine epsilon
             | (which lacks the required properties) -- poor wording on my
             | part. If you have numbers of impossibly large magnitude you
             | probably also want corresponding numbers of impossibly
             | small magnitude. You can do this in a nice, algebraically
             | satisfying way with infinitely many such numbers
             | (hyperreals), but I think if it weren't for the signless
             | zero and positive zero conflation, IEEE754's way would be
             | quite a reasonable finite precision approximation to this.
        
           | phkahler wrote:
           | Posits handle this by using the smallest non-zero number
           | where floating point would go to zero. They also use the
           | largest represent able number instead of infinity. These
           | exist for both positive and negative numbers. At least that's
           | the way I read it.
        
         | chrisseaton wrote:
         | Computers (obviously) have to approximate the majority of
         | actual mathematical numbers, as they do not have infinite
         | storage.
         | 
         | If you've got two numbers, +0.0000001 and -0.0000001, but you
         | can't represent that precision, can you see how it's less bad
         | to round to +0.0000 and -0.0000 rather than to just 0.0000?
         | It's encoding strictly more information.
        
           | bjourne wrote:
           | More information isn't better if that information isn't
           | useful. Does x*0 evaluate to 0.0? Not with -0 around. Does
           | x+0 evaluate to x? Maybe!
        
             | wnoise wrote:
             | IEEE 754 requires that -0.0 and 0.0 compare equal.
             | 
             | > Does x*0 evaluate to 0.0
             | 
             | No, but it will compare equal, unless x is either infinite
             | or a NaN.
             | 
             | > Does x+0 evaluate to x? Maybe!
             | 
             | Yes, unless x is either infinite or a NaN.
        
           | bendiksolheim wrote:
           | > it`s less bad
           | 
           | Really good point. My approach to this was "if it's not used
           | in any mathematical algorithms, why do we need it in
           | computers?". But in your example, you retain some information
           | even though you can't represent the whole truth. Thanks!
        
           | jayd16 wrote:
           | You could still use the bitwise -0 value to represent another
           | real number. Do you gain anything?
        
           | BeetleB wrote:
           | One should usually _not_ rely on this, unless your language
           | gives guarantees. I don 't think even IEEE 754 gives you the
           | guarantee you are implying.
           | 
           | To give you an idea, the C99 standard does not require signed
           | zeros, and if you have them, does not dictate the behavior
           | you are describing. I once worked on a commercial C compiler
           | and we produced a new version that resulted in a change of
           | sign of zero for the exact same computation (and even
           | "worse", would give a different sign on different machines
           | for the same compiler version). We discussed this thoroughly
           | and decided it was OK because our docs made it clear we
           | conform to C99 (which provides no guarantees on signed zero).
        
           | numlock86 wrote:
           | Ok, so what's true? -0<+0 or -0==+0
        
             | marcosdumay wrote:
             | You shouldn't really use equality on floating point
             | numbers, except on very special circumstances (and I
             | imagine the == behavior for 0 breaks things more often than
             | it helps). But the wikipedia page on -0 has your case
             | covered:
             | 
             | > According to the IEEE 754 standard, negative zero and
             | positive zero should compare as equal with the usual
             | (numerical) comparison operators, like the == operators of
             | C and Java. In those languages, special programming tricks
             | may be needed to distinguish the two values
        
               | brandmeyer wrote:
               | > You shouldn't really use equality on floating point
               | numbers, except on very special circumstances.
               | 
               | This is very common advice, so common that it gets cargo-
               | culted into situations where it is really quite poor.
               | 
               | Information storage, retrieval, and transmission systems
               | should faithfully deliver floating-point values that are
               | good to the last bit. Round-trips through databases,
               | transmission over network protocols, etc should all give
               | values back that are exactly identical to what was put
               | into them.
        
               | marcosdumay wrote:
               | Oh, sure. But those applications should also not use the
               | floating point equality operators. They deal with opaque
               | data, and should make sure not to corrupt it.
               | 
               | Keep in mind that the ISO standard does require that
               | floating point equality tests return false for values
               | that have the exact same binary representation, and that
               | not everything adheres to it and some environments may
               | give you false for identical values even when the
               | standard says it should be true. Also, != is not the
               | negation of == for floating point. So even using those
               | operators to test a round trip over those applications is
               | iffy.
        
               | rav wrote:
               | By "the last bit" do you mean the 32nd bit or the 64th
               | bit? :-)
               | 
               | Many times I've tracked down the place in our stack where
               | a double-precision value from user input accidentally
               | goes through a single-precision variable in some C code
               | somewhere and crashes some Python code later on because
               | the values don't match "to the last bit" in the way that
               | the programmer thought... But that's a bug in the C code
               | - I agree completely the the system SHOULD give the value
               | back that was put into it!
        
               | brandmeyer wrote:
               | This is actually _exactly_ what I mean. Its probably the
               | most common bug I 've come across in this class. I don't
               | expect unit tests to capture all rounding bugs (say, due
               | to serialization and de-serialization through text). But
               | I do expect to capture gross errors, such as an
               | inadvertent cast to lower-precision somewhere in the
               | pipeline.
               | 
               | I've worked with highly experienced and accomplished
               | software engineers that expected interchange through
               | protobuf or sql to be inaccurate due to rounding. No! If
               | you stick a finite number in, you should get the exact
               | same finite number back out again. Direct equality is
               | fine for most cases. The sign bit of zero and NaN should
               | also be returned faithfully and tested using memcmp when
               | required.
               | 
               | IMO, the payload bits of NaN should also be also returned
               | faithfully, but too many systems in common practice drop
               | them.
        
               | chrisseaton wrote:
               | > Round-trips through databases, transmission over
               | network protocols, etc should all give values back that
               | are exactly identical to what was put into them.
               | 
               | Yes that's true... but what's that got to do with using
               | an equality operator?
        
               | orthoxerox wrote:
               | IEEE 754 also defines a total order of all fp values,
               | where -0.0 immediately precedes 0.0
        
             | [deleted]
        
             | chrisseaton wrote:
             | You can look these things up for yourself - they're
             | standardised in most language's implementations in
             | something called IEEE 754. In the cases you've asked about
             | they're false and true. Is this what you want in all cases?
             | No. Is this what you want in some cases? Yes. It's a
             | tradeoff. You can still observe the difference by dividing
             | by zero (which should be another indication that these
             | aren't real numbers as we're conventionally understand
             | them.)
        
               | BeetleB wrote:
               | > they're standardised in most language's implementations
               | in something called IEEE 754
               | 
               | There is the IEEE 754, and there is the language's
               | standard. One should _always_ look at the latter because
               | it 's often the case that the language doesn't fully
               | conform to IEEE 754.
        
             | ben509 wrote:
             | They're equal. But, copysign(1.0, -0.0) == -1.0
        
           | harpiaharpyja wrote:
           | Reading your comment gave me a realization that transformed
           | my understanding of floats.
           | 
           | What just clicked for me was that in any system where we use
           | finite precision to store exponents, we can't actually have
           | zero as a normal value... we'll always underflow the exponent
           | before we get to actual mathematical zero.
           | 
           | So +0/-0 is actually a convenient misnomer. They really are
           | +/- epsilon.
           | 
           | The only way to have zero is if it's some specially handled
           | value like NaN. Which IEEE doesn't do and that's entirely
           | understandable.
           | 
           | Makes sense why you can never compare a subtraction of floats
           | to zero (it's beyond just "rounding errors") and the
           | existence of +0/-0 seems quite natural now.
        
             | ben-schaaf wrote:
             | The same is true on the other end of the limit. Infinity in
             | floating point really just means "some value larger than
             | can be represented".
        
         | boomlinde wrote:
         | _> Does anyone have a good example of a programming problem
         | where we _need_ signed zero? Or where it makes things
         | significantly simpler?_
         | 
         | Maybe when you're implementing floating point numbers in a way
         | that's simple and widely applicable?
         | 
         | I'm only half joking, too, though I can't tell you what exactly
         | having a distinct sign bit simplifies.
         | 
         | I can say off the bat that it is probably useful that a very
         | small quantity that might otherwise lose enough precision to
         | round to zero maintains its sign regardless.
        
         | an_d_rew wrote:
         | It's pretty common when, for example, you're computing the
         | flows in a bifurcating field.
         | 
         | Take 2d laminar flow around a circle. The flow field splits
         | right in the middle.
         | 
         | Signed zeros ensure that, along with graceful underflow, the
         | local solution is not wonky.
         | 
         | Lots of complex-arithmetic examples too.
        
         | forgetfulness wrote:
         | Floating point math was devised to be used in numerical methods
         | that are applied iteratively, like gradient descent. In that
         | world what you are always doing is "converging" to solutions
         | step by step, and a negative or positive zero can tell you
         | which direction you're converging from.
        
         | ben509 wrote:
         | 0 does double duty as meaning itself and to indicate underflow
         | due to multiplying very small numbers.
         | 
         | If you have a function that can experience underflow it can be
         | useful to preserve the sign of the underflowing value.
         | 
         | Otherwise you'd need more checks to get that information.
        
         | banachtarski wrote:
         | It's used when writing SIMD code all the time to quickly mask
         | bits as needed or to check the sign of a floating point number
         | with an SSE intrinsic. _mm_xor_ps(_mm_set1_ps(-0.f), reg) as an
         | example negates all four components of reg.
        
         | pfortuny wrote:
         | Exactly for things like OP's argument: 1/-0 is -inf, and that
         | may be important in asymptotics
        
         | linuxlizard wrote:
         | Latitude / Longitude coordinate as floating point.
         | 
         | https://gis.stackexchange.com/questions/211796/if-degrees-is...
         | 
         | I made the above post due to a bug in the GPS on our routers.
         | We had a customer close to the meridian in England.
         | 
         | http://www.thegreenwichmeridian.org/tgm/articles.php?article...
         | 
         | Western hemisphere is negative longitude, eastern hemisphere is
         | positive. If your degrees are 0 (within ~100km? I can't
         | remember exactly), then you still need to know if you're east
         | or west of the meridian.
        
         | jerf wrote:
         | I agree with many of the other replies, but I would also add,
         | perfectly serious and with no sarcasm, do not be fooled;
         | computers do not use "math" numbers. They use what they use;
         | machine-word bounded integers and IEEE floats most commonly,
         | unbounded integers, some variants on rational numbers, and
         | sometimes some more exotic things, but they never use real
         | numbers. They're bounded to the computable numbers.
         | 
         | So whether or not there's a -0 or +0 in some "math" isn't
         | relevant, because computers aren't using "some math" but very
         | specific mathematical constructs that must be understood on
         | their own terms. I haven't seen very many mathematical systems
         | that have a reified "NaN" object that can be explicitly passed
         | around as a valid value to functions. (I know of many systems
         | that have a "bottom" but I would say bottom is usually
         | presented not as an object you can "have" but as a property of
         | some mathematical object. Haskell for instance uses this idea;
         | there are some trivial ways to have or produce something that
         | has the property of being "bottom", like calling "error", but
         | you can't just "have the bottom value".)
         | 
         | Moreover, there are mathematical systems in which such things
         | can appear. There are many exotic and interesting number
         | systems in the mathematical world, which even a bachelor's
         | degree in mathematics may only scratch the surface of,
         | depending on which junior/senior level courses you take. Real
         | numbers are without a doubt the most studied, and they do not
         | contain a -0 (though even then you'll still see it show up
         | sometimes as a special notation in limits), but they are the
         | beginning of number systems, not the end.
         | 
         | I mention all this because it's important; it's a very common
         | misconception that computers use the numbers like you learned
         | in school, and it will lead to nothing but pain. The next
         | misconception is that, ok, sure, they aren't those numbers
         | _exactly_ , but they're so close that I don't have to worry
         | about it. This works as long as you don't push your floats too
         | hard, and a lot of us don't, but also breaks down surprisingly
         | quickly. It's important for programming professionals to
         | understand in general that IEEE floats are their own thing.
         | Whenever I use them I do at least take a couple of seconds to
         | double-check mentally that the sharp pointy bits aren't going
         | to stab me, even for simple things like adding durations of a
         | request to some floating point accumulator for metric purposes.
        
         | johnmyleswhite wrote:
         | Negative zero was introduced because of branch cuts:
         | https://people.freebsd.org/~das/kahan86branch.pdf
        
         | isolli wrote:
         | A distinction can be made when considering the limit of a
         | sequence. If a sequence converges to zero from positive values
         | (sometimes written -> 0+), then the inverse of the sequence
         | will diverge to +inf, while if the sequence converges to zero
         | from negative values (-> 0-), the inverse will diverge to -inf.
         | 
         | As a sibling comment wrote, rounding numbers to -0 and +0 can
         | provide extra information, though it may not be useful in all
         | contexts.
        
         | brandmeyer wrote:
         | Sign/magnitude ADCs almost have signed zero in hardware, by
         | generating a sign bit and zero or more magnitude bits. The
         | typical method to map to voltages doubles the span between
         | adjacent values and skips over zero. So a 2-bit sign/magnitude
         | ADC measures values in the series {-3, -1, 1, 3}.
         | 
         | So strictly speaking this number system doesn't have a
         | representation of zero at all. Tiny measurements either round
         | up or round down to +/- 1.
        
       | posterboy wrote:
       | the way c does because it is written in c++ using scanf lulz
        
       | JoeAltmaier wrote:
       | Signed infinity is nowhere near the 'expected result'. Zero has
       | no sign. NAN would be a better result off the top of my head.
       | 
       | But I see from the standard that dividing by zero returns
       | infinity with the xor of the dividend and divisor. This also
       | makes no sense - since zero has no sign, its not possible to tell
       | what kind of infinity would result. It's strange that the
       | standard permits both the infinity result from dividing by zero,
       | and simultaneously supports signed zero.
       | 
       | <edit: add xor>
        
       | magicalhippo wrote:
       | I recall there being an issue with double.GetHashCode() in the
       | early versions of .Net, where it would return different hash
       | values for 0.0 and -0.0.
       | 
       | That got fixed, but it seems a variation with signed NaN recently
       | got fixed[1] in .Net Core (taking care to handle all the possible
       | NaN values).
       | 
       | Floats are deceptively easy to use. Which is nice but kinda sucks
       | too, given all the footguns they bring to the party.
       | 
       | [1]: https://github.com/dotnet/runtime/issues/6307
        
         | mattgreenrocks wrote:
         | The fact that NaN is technically a set of values in IEEE-754
         | (rather than just one agreed-upon value) was quite eye-opening
         | to me.
        
         | TacticalCoder wrote:
         | > I recall there being an issue with double.GetHashCode() in
         | the early versions of .Net, where it would return different
         | hash values for 0.0 and -0.0.
         | 
         | I never thought about that (I avoid FP as much as I can) but,
         | oh boy, the can of worms!
         | 
         | .Net (or Java) OOP where an object's hashcode needs to give the
         | same (or not?) value for 0.0 or -0.0: this is the kind of stuff
         | nightmares are made off.
         | 
         | I'm sure this can be turned into some very funny "Java
         | puzzler".
        
         | emergie wrote:
         | You inspired me to check java world.                 // 0.0d /
         | 0      equals 0x7ff8000000000000 (NaN)       // Math.sqrt(-1)
         | equals 0xfff8000000000000 (NaN)       // 0x0p+0d  is a funky
         | way to specify 0x0000000000000000 (0)       // -0x0p+0d is a
         | funky way to specify 0x8000000000000000 (-0)       // without
         | 0xHEXp+NUMd my compiller optimizes "-0" literal to 0
         | // 0 == -0           0x0p+0d == -0x0p+0d                //
         | hashCodes for 0 and -0 are different
         | Double.hashCode(0x0p+0d) != Double.hashCode(-0x0p+0d)
         | // hashCodes for different NaNs collapse to the same value
         | Double.hashCode(0.0d / 0) == Double.hashCode(Math.sqrt(-1))
        
         | emergie wrote:
         | What is wrong in having different hashes for different numbers?
         | 
         | https://float.exposed/0x0000000000000000
         | 
         | https://float.exposed/0x8000000000000000
        
           | magicalhippo wrote:
           | If you compare for equality then those two numbers, 0.0 and
           | -0.0, are considered equal. It seems a lot of people consider
           | that a good reason for them to have the same hash value,
           | which I consider entirely fairly reasonable.
           | 
           | Of course since NaN != x, whatever x is (including infinity
           | and NaN), one could argue it's fine for different NaNs to
           | return different hash codes. But I think most people think of
           | NaN as one thing, and not the 9007199254740990 or so
           | different NaN encodings[1] there are in a double.
           | 
           | [1]: https://en.wikipedia.org/wiki/IEEE_754-1985#NaN
        
       | pfsalter wrote:
       | PHP just refuses to divide by zero:                   php >
       | $minus_zero = -0.0;         php > $plus_zero = +0.0;         php
       | > var_dump(1.0 / $minus_zero);         PHP Warning:  Uncaught
       | DivisionByZeroError: Division by zero in php shell code:1
        
         | [deleted]
        
         | bakje wrote:
         | Actually as shown by your output it doesn't completely refuse
         | to divide by zero, a warning means that execution continued.
         | 
         | The result of that division is a float with a value of -INF,
         | INF being a constant that PHP treats as infinite.
         | 
         | But as of PHP 8 dividing by zero causes a fatal error and
         | execution is halted.
         | 
         | This site is really good for comparing results in different PHP
         | versions: https://3v4l.org/9Tl1I
         | 
         | I actually wasn't aware that PHP had an INF contant but seeing
         | the warning in your output prompted me to dig a little bit
         | deeper :)
        
       ___________________________________________________________________
       (page generated 2021-03-05 23:02 UTC)