A few times I have told the anecdote that the singly most baffling thing I ever saw in a code review — not the most insecure, just the most “how could a real programmer have written this? how could this ever make sense?” thing — was simply a C++ variable “number_of_trucks” … declared as float. Unambiguously referring to real physical trucks in a fleet.

Reader, it’s been over ten years and I am blowing the gods damn whistle. I had edited that story to protect the guilty: the variable was named number_of_planes. It was shipped by a company whose name begins with “B” and rhymes with “GOING out of business.”

Also if you don’t know what a float is (because you’re not a programmer or have only worked with very high level languages that try to conceal these details) then my horror makes no sense so I will break it down for you

If you declare a number value to be a float, that is telling the computer two things:

  • first, that the value is allowed to be fractional and not just whole numbers (integers). This means that if someone reports that the fleet gained 2.3 planes or lost 0.01 planes, the computer would be like yeah, sure, that makes sense, let me write that down.

  • second, doing math with fractions is much more computationally complicated than whole numbers. Telling the computer a value is a “float” is explicitly telling it that you want it to use the fastest methods it has available to do the math, even if they’re not 100% accurate down to the smallest fraction of a fraction. You are saying it’s okay to lose track of a hundredth of a plane here or there as long as you count the planes really fast.

The intended use of floats is things like video game graphics: you can’t tell if the height of the enemy is 6.200002 meters or 6.2 meters exactly, and letting the computer not worry about the difference makes the calculations much faster. You should never, ever use floats for things like money, because over the course of many successive adds and subtracts, entire cents or dimes will just pop in and out of existence. Or, like, some unspecified fraction of a plane, which is probably not what you want.

@0xabad1dea

A float makes the bits not sink in water.

@0xabad1dea Sounds like the perfect use case for Boeing then. That door did pop out of existence, after all.

@wasmitnetzen
@0xabad1dea

Only 0.999999999 of the plane landed.

@wryanfisher @wasmitnetzen @0xabad1dea

Less than 0.999, assuming the door weighed 200kg

@naught101
@wasmitnetzen @0xabad1dea

Fair. Also, all of the plane landed. Just, not together. ;D

@wasmitnetzen @0xabad1dea The door plug is maybe 0.002 planes.
@wasmitnetzen @0xabad1dea the door size was set to 0.99989 and the port size to 1.0000003
@0xabad1dea
Floats also allow some languages to write cool documentation like “If <language> encounters a number beyond the bounds of the int type, it will be interpreted as a float instead. Also, an operation which results in a number beyond the bounds of the int type will return a float instead.” 🙃
@0xabad1dea Well, I suppose Alaska Airlines did lose approximately 0.01 planes recently ✈️

@0xabad1dea A quibble: floating point numbers give exact values for addition, multiplication and subtraction involving integers if the results aren't too large.

In 32-bit floating point, you can exactly represent all integers up to 16,777,217.

> You should never, ever use floats for things like money

You can't do things like compound interest and mortgage payments with integer arithmetic! 😁

---

I have a relevant story here that you might find amusing.

1/

@0xabad1dea I worked for Ripple, not nice people at all. I got put on a project with a young man with very strong beliefs about his ability to write computer programs who had "written" a trading backend in "C++" - really C.

(One of his beliefs, for example, was that making all variables static and global made the program run faster. Indeed, he had a lot of weird beliefs about what made programs faster, but since he refused to do any form of benchmark, I was skeptical.)

2/

@0xabad1dea The project was specc'ed to use integer arithmetic, so I spent a week writing a nice 64-bit fixed point arithmetic system.

But this nice young man refused to cooperate. One of the things I'd been brought in to do was write unit tests, something he was completely against, so he'd made all these changes and never run the tests.

I got fired. But they were too stupid to remove my privileges for the repo, so I watched his "work".

3/

@0xabad1dea
First he ripped out my 64-bit fixed point arithmetic, and replaced it with `int128_t` - which works by using two hardware 64-bit ints!

My quick benchmarks showed me that this slowed all arithmetic down by a factor of about five.

But then, even worse, since he had no understanding of how computer arithmetic worked, all his intermediate calculations were in 64-bit floating point, which then got converted back into `int128_t`.

Of course, the product never came out.

/thread

@TomSwirly @0xabad1dea

Many Many years ago, I have written systems using "double" types/variables for integer values -- in languages where there was no "long integer" type. In those cases, where you need to store exact integer values over 32,767, ... Well, the "double" type can do that. Sure, it's slow and introduces risks. But when you don't have any viable "long int" type, you use what you have.

@TomSwirly @0xabad1dea well Yes you CAN do compound interest etc calculations using integers only. We did it all the time in COBOL.

The trick is to let the integer represent 1/1.000.000 (.000) th of the "real" value.

@bertkoor @0xabad1dea That's indeed the "fixed point" I'm taking about later in the story, so you're right, I should have been more specific.

(But if you do that, you still have the possibility of pennies appearing and disappearing unless you are careful...)

@TomSwirly @0xabad1dea
In my experience pennies have the tendency to (dis)appear, no matter how you represent them. Being really careful is sometimes not even enough, they take you by surprise.
Every. Single. Effing. Time.

@bertkoor @0xabad1dea You ain't joking, I have gotten bit with that before. though not in Cobol. The 64-bit fixed point project was fun though - partly because I'd done this before, partly because I knew no one else would be able to find my mistakes and by that point I was pretty sure it wasn't ever going to market... ah well!

(I never wrote any Cobol but I did help an awful lot of undergrads debug their Cobol programs a long time ago!)

@bertkoor @TomSwirly @0xabad1dea yeah, I was rather surprised today when I implemented some software to try to calculate the interest the same way my bank does. After a bunch of trial and error, I finally got it to work (with one month on one account off by a penny but correct the next month)... as long as I never round anything to a penny except for presentation purposes

I really wish banks had to disclose their calculation methods with much more detail

@TomSwirly @0xabad1dea

You can't do them with integers, except you *CAN* if you kinda... cheat!

You definitely don't use floats.

You use fixed-point with as many decimal places as you need to make sure your calculations will always be as accurate as you need.

It's basically two integers superglued together.

@nyankat @TomSwirly @0xabad1dea also, bankers rounding is a thing to prevent error from accumulating, and can be used to make fixed point more practical

(bankers rounding basically special cases the .5 situation, rounding it to the nearest *even* number, instead of always up. so, rounding 0.5 to the nearest integer produces 0, rounding 1.5 to the nearest integer produces 2.)

@bhtooefr @0xabad1dea @TomSwirly Oh yeah! I did know about that, but had forgotten. Geez, I think I learned that in fuckin' Junior High advanced math and then used it never lol

Fuck, that was literally 30 years ago

@TomSwirly @0xabad1dea Sure you can, it's called "fixed point" and it's quite common.
@landley @0xabad1dea Ah, sorry, yes, later in this thread I tell a funny story about writing a fixed point system even...
@TomSwirly @0xabad1dea Navigating reply threads in mastodon is... not ideal.
@landley @0xabad1dea Yes, indeed, but at least this place is, well, not Musk-free but at least Musk-lite.
@0xabad1dea It isn’t quite like that. Floats are still bound by hard rules. The heuristic that results are off by a millionth or so is not one of those rules. All integers up to ±2^24 have exact representations in binary32. Floats might as well be native integers under that constraint. Still, it’s very questionable to say the least.
@jonathanavt my sibling in posting, pasting the entire Wikipedia article on IEEE floating point into my thread would not help non-programmers understand the fundamental general issue
@0xabad1dea I really hope this was in some business inventory thingamajig and not in maintenance or flight software.
@0xabad1dea thank you for the explanation
@0xabad1dea Javascript developers intensively sweating

@aris @0xabad1dea When are they ever not?

"I have made some terrible decisions"

@0xabad1dea well if a panel is missing you do t have a full plane. The programmers knew their company. No reason to be snarky. What are a few bits and bolts between friends;)
@0xabad1dea You need to tell that story to JavaScript.
@0xabad1dea The bigger horror here is that this represents a programmer who didn't know the basics behind dealing with numbers in code. Where else did they make this mistake? And how did no one catch it. 😱
@syntaxseed @0xabad1dea Well the disadvantage of finding errors in airplane code is that, once the error occurred, in most cases the computer where it happened "pops out of existence", so debugging becomes virtually impossible.
@0xabad1dea I have terrible news for you about the serialization format chosen for most new APIs endpoints.
@objectObject
If you are referring to JSON: It writes numbers as decimal strings. Good serialization libs can handle them without losing precision.

@xris true, eg pydantic does this if you specify that a field is a Decimal. But deserializing to float64 is quite common.

The default in Python's json module is that integer values get turned into int and anything with a decimal is a float, which can cause bugs with trivial examples like summing up the price of items to get an order total, unless you convert them to Decimal first.

@xris I've seen financial APIs in the US provide monetary amounts as an integer in cents because that will work correctly in float64 up to a very high monetary amount.
@0xabad1dea When you think about recent happenings, it kinda makes sense. There were apparently incomplete planes being put into the skies and doors popping off.

@0xabad1dea floating point errors are the actual bane of my existence.

I think another aspect to mention is that the errors also occur because computers don't do math like humans. Everything has to first be converted to binary, a base 2 number system, and humans use a base 10. Some numbers just don't translate very neatly in the conversion, eg. Doing the calculation 0.9 + 0.1 can equal 0.9999999999999999999... because floating point errors.

@0xabad1dea That was probably really useful when fractional planes fall off, right?
@0xabad1dea ok, there's a lot of variations of this same joke here, most better than mine; which is the best?
@0xabad1dea Having spent too much of my career dealing with floating-point numbers in computers, I'm delighted to note that a float is also a type of steel file used in shaping wood. Also I'm considering that a Guinness-and-cherry-ice-cream float could be a research topic.

@0xabad1dea 1. Thank you for this explanation. I was a programmer for a while and I never actually knew this.

2. Boeing clearly doesn't care about losing a fraction of a plane here or there.

@0xabad1dea it would make sense for ships, though. Because you know, they float.
@0xabad1dea I knew what floats were, prior to this explanation, but if I hadn't, I think I would now. 👍
@0xabad1dea A float is fine for a fractional plane, when bits of it have fallen off.
@telescoper @0xabad1dea yeah, i think in #boeing's case it might actually be an appropriate choice. possibly even prescient.
@telescoper @0xabad1dea A few bolts on a door plug? That's just a rounding error…
@0xabad1dea My mind was blown when it was suggested to me to just calculate everything to desired-precision power of 10, and _just use int_. Cheat in a decimal point as a matter of print formatting. Oh- YEAH! Life changing, yo =)
@0xabad1dea i mean given what we know now, that granularity may actually be desirable for them