5 ms·
Most ints are not floats
- deleted 1y ago[deleted]
- taeric 1y agoIt is a shame we tend to teach floats as the computer version of reals. Thinking of them as "scientific numbers" really helps a ton with this.
- atn34 1y agoI want to make a Birds Aren't Real[0] style t-shirt that says "Floats Aren't Real" [0]: https://en.wikipedia.org/wiki/Birds_Aren%27t_Real https://en.wikipedia.org/wiki/Birds_Aren%27t_Real
- tialaramex 1y agoI would buy this T-shirt. I would also take "Floats Aren't Normal"
- munchler 1y agoTrue, but we also have to be careful about teaching ints as the computer version of integers.
- jrvieira 1y agowait, why?
- neepi 1y agoProper integers aren’t bounded. Computer ints are.
- jrvieira 1y agoUnbounded integer types exist, which have infinite precision in theory and are only limited by available memory in practice. You can make the argument that "proper" integers are also bounded in practice by limitations of our universe :)
- layer8 1y agoUnbounded integer types aren't ints. The important point is that the arithmetic operators on int perform modulo arithmetics, not the normal arithmetics you would expect on unbounded integers. This is often not explained when first teaching ints.
- adastra22 1y agoIn many langue’s (e.g. Python, so not even obscure languages), ints are unbounded.
- layer8 1y agoThat’s not the notion of ints the article, nor GP by “computer ints”, was referring to. Python is rather atypical in its nomenclature here. Arbitrary-precision integers are generally called “integer” or something like “bigint”.
- MathMonkeyMan 1y agoUnsigned ints are the non-negative integers mod 2^n. Signed ints behave like the integers in some tiny subset of representable values. Maybe it's something like the interval (-sqrt(INT_MAX), sqrt(INT_MAX)).
- AlotOfReading 1y agoThat's one way of looking at them. You can also look at the signed integers as bounded 2-adic numbers.
- LegionMammal978 1y ago"Bounded 2-adic integers" would only make sense if you were bounding the 2-adic norm. Integers mod 2^n would be closer to "approximate fixed-point 2-adic integers". (Alas, most languages don't expose a convenient multiplicative inverse for their integer types, and it's a PITA to write a good implementation of the extended Euclidean algorithm every time.)
- sjrd 1y agoSigned ints are also the integers mod 2^n. The beauty of modular arithmetics is that it's all equivalent. At least for all the operations that work in modular arithmetics in the first place. They just have different canonical representatives for their respective equivalence classes, which are used for the operations that don't work in modular arithmetics (like divisions, comparisons or conversions to string with a sign character).
- SkeuomorphicBee 1y agoNot in C. In C signed integer overflow is underined behaviour that may or may not be compiled to the equivalent of mod arithmetic dependingonthe whims of the compiler.
- adastra22 1y agoC oddities should be relegated to a footnote, not define what computer science is.
- perching_aix 1y agoAre they even reals? Math classes were a while ago at this point, but I'm fairly convinced they're just rationals. Not trying to be pedantic, just wondering.
- jrvieira 1y agoYes, all floating numbers are rational. (It's also true that they are all reals but i get your point.)
- neepi 1y agoThey aren’t pure rational either. They are a subset of rational numbers.
- perching_aix 1y agoI think that's more of how one frames it, no? Like you won't be able to store any arbitrary rational in a float, as you'd need arbitrarily large storage for that. But all the numbers a float can store are rationals (so excluding all the fanciful IEEE-754 features of course).
- tialaramex 1y agoIt's not so much the need for arbitrary storage, the problem is that even easy rationals can't be expressed in the IEEE floats Take realistic::Rational::fraction(1, 3) ie one third. Floats can't represent that, but we don't need a whole lot of space for it, we're just storing the numerator and denominator. If we say we actually want f64, the 8 byte IEEE float, we get only a weak approximation, 6004799503160661/18014398509481984 because 3 doesn't go neatly into any power of 2. Edited: An earlier version of this comment provided the 32-bit fraction 11184811/33554432 instead of the 64-bit one.
- neepi 1y agoThey aren’t reals. They aren’t continuous and are bounded.
- analog31 1y agoThe pitfalls of floats were taught when I was a college math major. That was in the mid 80s.
- capyba 1y agoIsn’t the `real` datatype in Fortran a float64? Or am I making that up?
- PaulHoule 1y ago... but people are in the habit of using doubles. Many languages, like Javascript, only support doubles and int32(s) do embed in doubles. I have some notes for a fantasy computer which is maybe what would have happened if Chinese people [1] evolved something like the PDP-10 [2] Initially I was wanting a 24-bit wordsize [3] but decided on 48-bit [4] because you can fit 48 bits into a double for a Javascript implementation. [1] There are instructions to scan UTF-8 characters and the display system supports double-wide bitmap characters that are split into halves that are indexed with 24-bit ints. [2] It's a load-store architecture but there are instructions to fetch and write 0<n<48 bits out of a word even overlapping two words, which makes [1] possible; maybe that write part is a little unphysical [3] I can't get over how a possible 24-bit generation didn't quite materialize in the 1980s, and find the eZ80 evokes a kind of nostalgia for an alternate history [4] In the backstory, it started with a 24-bit address space like the 360 but got extended to have "wide pointers" qualified by an address space identifier (instead of the paging-oriented architecture the industry) really took as well as "deep pointers" which specify a bitmap, 48-bit is enough for a pointer to be deep and wide and have some tag bits. Address spaces can merge together contiguously or not depending on what you put in the address space table.
- jerf 1y ago"I can't get over how a possible 24-bit generation didn't quite materialize in the 1980s, and find the eZ80 evokes a kind of nostalgia for an alternate history" Well... it depends on how you look at it. While the marketers tried to cleanly delineate generations into 8- and 16- and 32-bit eras, the reality was always messier. What exactly the "bits" were that were being measureds was not consistent. The size of a machine word in the CPU was most common, and perhaps in some sense objectively the cleanest, but the number of bits of the memory bus started to sneak in at times (like the "64 bit" Atari Jaguar with the 32-bit CPU because one particular component was 64 bits wide). In reality the progress was always more incremental and there are some 24-bit things, like, the 286 can use 24 bits to access memory, and a lot of "32 bit graphics" is really 24 bits because 8 bits for RGB gets you to 24 bits. The lack of a "24-bit generation" is arguably more about the marketing rhetoric than the lack of things that were indeed based around 24 bits in some way. Even today our "64-bit CPUs" are a lot messier than meets the eye. As far as I know, they can't actually address 64 bits of RAM, there are some reserved higher bits, and depending on which extensions you have, modern CPUs may be able to chew on up to 512 bits at a time with a single instruction, and I could well believe someone snuck something that can chew on 1024 bits without me noticing.
- dmurray 1y agoThis should be obvious. There are the same number of 32-bit integers as 32-bit floats [0], so for every float that is not an int, there exists an int that is not a float. Clearly most floats cannot be represented as integers, so the converse must be true as well. But I still see people building systems where implicit conversation of float to int is not allowed because "it would lose precision", but that allow int to float. [0] don't reply to me about NaNs, please
- worik 1y ago> This should be obvious Yes They are different types They are different things They are related concepts, that is all
- Kranar 1y agoSure but at least in my experience it's rare to convert 32 bit ints to 32 bit float. Usually the conversion is 32 bit int to 64 bit float, which is always safe.
- deleted 1y ago[deleted]
- nofriend 1y agoFloats have a fixed accuracy everywhere. Ints have a variable accuracy across their range. When you convert from int to float, the number stays accurate to however many digits, say 8 digits for single precision. Ints have a fixed precision everywhere, whereas for floats it varies. A given float might be accurate to one part in 10^30. When you cast to int, you get accuracy to within 1 part in 1. So you lose far more orders of magnitude of precision converting from float to int then you lose in order of magnitude of accuracy converting from int to float.
- titzer 1y ago> When you convert from int to float, the number stays accurate to however many digits The point of the article is that this "however many digits" actually implies rounding many numbers that aren't that big. A single precision (i.e. 32-bit) float cannot exactly represent some 32-bit integers. For example 1_234_567_891f is actually rounded to 1_234_567_936. This is because there are only 23 bits of fraction available (https://en.wikipedia.org/wiki/Single-precision_floating-point_format https://en.wikipedia.org/wiki/Single-precision_floating-poin...).
- tikhonj 1y agoSomething I found really annoying in the Avro spec is that they automatically convert between ints/longs and floats/doubles in their backwards compatibility system. That just seemed like an unforced error to me. (Maybe it's changed in newer versions of the standard?)
- deckar01 1y agohttps://gist.github.com/deckar01/f77d98550eaf5d9b3a954eb034388f86?permalink_comment_id=5627238#gistcomment-5627238 https://gist.github.com/deckar01/f77d98550eaf5d9b3a954eb0343... Here is a visualization I made recently on the density of float32. It seems that float32 is basically just PCM, which was a lossy audio compression exploiting the fact that human hearing has logarithmic sensitivity. I’m not sure why they needed the mantissa though. If you give all 31 bits to the exponent, then normalize it to +/-2^7, you get a continuous version of the same function.
- tialaramex 1y agoSo, PCM isn't the thing you meant here. PCM just means Pulse-code modulation, you're probably thinking of a specific non-linear PCM and maybe that was even the default for some particular hardware or software you used, but that's not what PCM itself means and these days almost everything uses Linear PCM.
- userbinator 1y agoI think G.711 PCM is what the OP meant.
- tialaramex 1y agoWow. G.711 is extremely obsolete. Interpreting PCM as G.711 (which is from the 1970s) is about similar to if somebody said "Windows" but meant Windows 2.x the 1980s DOS-based Microsoft GUI. I guess I don't have to feel like I'm the oldest person reading HN.
- userbinator 1y agoIn the telco industry, "PCM" or more precisely "PCMA" and "PCMU", refers to G.711. It's still the default fallback for VoIP applications.
- timewizard 1y ago> It seems that float32 is basically just PCM float has higher accuracy around 1.0 than around 2*24. This makes it quite a bit different from PCM which is fully linear. Which is probably why floating point PCM keeps it's samples primarily between -1.0 and +1.0. > which was a lossy audio compression It's not lossy. Your bit depth simply defines the noise floor which is the smallest difference in volume you can represent. This may result in loss of information but at even 16 bits only the most sensitive of ears could even pretend to notice. > If you give all 31 bits to the exponent, then normalize it to +/-2^7, you get a continuous version of the same function. You'll extend the range but loose all the precision. This is probably the opposite of what any IEE754 user actually wants.
- furyofantares 1y agoWell yes. Given N bits: - Most floats are not ints. - There are the same number of floats as ints. - Therefore, most ints are not floats.
- cozzyd 1y agoPedantically there are fewer floats because of NaNs and double counting of zero
- derriz 1y agoThis is a fairly obvious one? Although I've mainly encountered the effect with long to double conversion. On the other hand, floating point is the gift that never stops giving. A recent wtf I encountered was partly caused by the silent/automatic conversion/casting from a float to double. Nearly all C-style languages do this even though it's unsafe in its own way. Kinda obvious to me now and when I state it like this (using C-style syntax), it looks trivial but: (double) 0.3f is not equal to 0.3d The wtfness of it was mostly caused by other factors (involving overloaded method/functions and parsing user input) but I realized that I had never really thought about this case before - probably because floats are less common than doubles in general - and without thinking about it, sort of assumed it should be similar to int to long conversion for example (which is safe).
- secondcoming 1y ago-Wfloat-conversion will warn about this. Been bitten by it too.
- taneq 1y agoThis sort of thing is why you never compare floating point numbers for equality. Always compare using epsilons appropriately chosen for the circumstances. Floats are Sneaky and Not to be Trusted. :D
- sjrd 1y agoAlways... except when you're actually writing floating point operations. If I'm implementing `sqrt`, I'd better make sure the result is exactly the expected one. Epsilon is 0 in all my unit tests. ;)
- taneq 1y agoThis is true! As an implementor of floating point operations, you want to be exactly correct for all values (glares at Intel :P ) However, as a consumer of said floating point operations, I'm still gonna treat everything as Sneaky And Not To Be Trusted. :P Especially in C++ where this attribute is largely supplied by the compiler being /r/iamverysmart about this sort of thing.
- petermcneeley 1y agoAnother unfortunate fact is that max int (signed and unsigned) is also not a float. This means you cannot write clamped ftoi conversion only in floating point (because the value is not representable). This is why webgpu (wgsl) does not fully saturate on ftoi https://www.w3.org/TR/WGSL/#floating-point-conversion https://www.w3.org/TR/WGSL/#floating-point-conversion
- tedunangst 1y agoI'll take the contrary position and argue that most ints are floats, because ints are not uniformly distributed. 0, 1, 10, etc. are far more common.
- stkdump 1y agoFar more common than what exactly? Because if you look at the range of the exponent, you should still come to the conclusion that floats can represent more non-integer numbers than integer numbers.
- GianFabien 1y agoI have been writing software for decades in areas ranging from industrial control to large business systems. I almost never use floats or doubles. In almost all cases 32 bit integers (and sometimes U64int) with some scaling suffices. Perhaps it is the FORTRAN overhang of engineering education that predisposes folks to using floats when Int32/64 would be fine. I shudder as to why in JavaScript they made Number a float/double instead of an integer. I constantly struggle to coerce JS to work with integers.
- squirrellous 1y agoTrue but misleading. Like one of the other commenters also mentioned, most integers are small. For 32-bit you might run into integers above 2^23 bits once in a while, but for 64-bits it’s really not that common to have integers above 2^53, unless it’s a bit pattern instead of a natural number. So you could reasonably say “most integers _are_ 64-bit floats.”
- fjfaase 1y agoA little known fact is that some intel processors use 80 bit registers to store double values, which can result in programs behaving differently based on the optimization level, because if values are stored in memory, like when building for debug, they are rounded.
- rurban 1y agoBut all int32 can be exactly represented by float64, which luajit uses extensively.