Live data from Hacker News

Floating Point Visually Explained (2017)

fabiensanglard.net

91–100 of 101 posts

Re: Floating Point Visually Explained (2017)

#91

Excellent article! Just one thing surprised me: > While I was writing a book about Wolfenstein 3D[1], I wanted to vividly demonstrate how much of a handicap it was to work without floating point I would've expected fixed point to work fine for games, because that's a domain where you know the data, and in particular the dynamic range, in advance, so the 'automatically adjust to whatever dynamic range happens to be in…

[deleted]

Re: Floating Point Visually Explained (2017)

#92
This is a bit odd:

"Trivia: People who really wanted a hardware floating point unit in 1991 could buy one. The only people who could possibly want one back then would have been scientists (as per Intel understanding of the market). They were marketed as "Math CoProcessor". "

The 486DX (1989) was already common in 91/92 and came with a floating point unit. I had a 50mhz 486DX, and I was not by any means wealthy. FP unit was certainly used by lots of software, especially things like Excel, but C compilers certainly produced code for it if you had one.

Likewise, the 68040 (1990) had onboard FP. Macintosh Quadra, Amiga 4000, and various NeXT models had it.

Yes if you bought a 386 you often had to get a floating point co-processor as upgrade, but it wasn't _that_ uncommon. Same on the 68k series; I knew people with Atari MegaSTes (68000) that bought an FP co-processor. They weren't astronomers :-)

This feels like recent history, am I really that old?

Re: Floating Point Visually Explained (2017)

#93
post #88

Earlier quoted context omitted.

Sure, I had to wrestle with this a bit myself: to make it easier, imagine a 16-bit floating point format (P&H call this the "Nvidia format", but I can't find that documented anywhere but there): 1-bit sign, 5-bit (biased) exponent, 10-bit mantissa. One thing that TFA leaves out about floating point mantissas is that there's an implicit leading 1, so a 10-bit mantissa of 1111100000 would be interpreted as (binary) 1.1…

> imagine a 16-bit floating point format (P&H call this the "Nvidia format", but I can't find that documented anywhere but there): 1-bit sign, 5-bit (biased) exponent, 10-bit mantissa According to Wikipedia ( https://en.wikipedia.org/wiki/Half-precision_floating-point_... ), this is the IEEE 754 standard binary16 format.

Sort of - I skipped over subnormal numbers.

Re: Floating Point Visually Explained (2017)

#94
post #53

Fabien Sargland is the same guy who wrote 2 books on a deep dive into 2 game engines: Wofenstein 3D and Doom which are great reading and I really recommend them to the HN crowd (can be downloaded for free): https://fabiensanglard.net/gebbwolf3d/ https://fabiensanglard.net/gebbdoom/

He also recently had a series of articles about the various ports of Out of this World/Another World to various systems which are well worth reading if you're into this sort of thing

Re: Floating Point Visually Explained (2017)

#95

Earlier quoted context omitted.

In practice, subnormal are very rarely used. Most compiler disable subnormals when compiling with anything other than -O0. It takes over a hundred cycle to complete an operation. Demo: #include int main () { volatile float v; float acc = 0; float den = 1.40129846432e-45; for (size_t i; i With -01: $ gcc float.c -o float -O1 && time ./float ./float 8.93s user 0.00s system 99% cpu 8.933 total With -O0: $ gcc float.c -o…

I looked at the asm generate from my original example and they generate very different codes, gcc applies other optimization when compiled with -O1. I've been fighting the compiler to generate a minimal working example of the subnormals, but didn't have any success. Some things take need to be taken in account (from the top of my head): - Rounding. You don't want to get stuck in the same number. - The FPU have some a…

Shouldn't i be initialized?

Re: Floating Point Visually Explained (2017)

#96

I wonder why the significand is represented as a > 1 number. It complicates representing zero (making it a special case not covered by the article of defining exponent=0, mantissa=0 to mean zero). Is it for the purpose of simplifying arithmetic operations or is it to minimize the number of redundant representations of zero?

The leading 1. prefix can be omitted from the binary representation thus saving a bit in the process.

That doesn't answer my question, though. I'm asking why the significand is in the range 1-2 instead of 0-1.

Re: Floating Point Visually Explained (2017)

#97

Earlier quoted context omitted.

I looked at the asm generate from my original example and they generate very different codes, gcc applies other optimization when compiled with -O1. I've been fighting the compiler to generate a minimal working example of the subnormals, but didn't have any success. Some things take need to be taken in account (from the top of my head): - Rounding. You don't want to get stuck in the same number. - The FPU have some a…

Shouldn't i be initialized?

lol, how the compiler didn't warn about uninitialized variable

Re: Floating Point Visually Explained (2017)

#98
post #58

Earlier quoted context omitted.

Ackchyually... The IEEE-754 has a lot of redundant representation. Not where you would expect though. Caveat: Those features are invaluable for some niche applications, but not for the average joe. To start. Every IEEE-754 float has two zero representation: one for positive zero and another negative negative zero (sic). The special numbers are another source of redundancy. The the double format, have about 9,007,199,…

> If that wasn't bad enough, since the magnitude of the numbers follows a normal distribution (someone whose name I forgot's law), the most significant bits of the exponent field are very rarely used. The IEEE-754 encoding is suboptimal. But isn't that accounted for by the fact the floating point number distribution is non-uniform? Half of all floating point numbers are between -1 and 1.

Hm. I don't know.

My reasoning is about how much information can be encoded in the format.

The IEEE-754 double format have 11 bits to encode the exponent and 52 bits to encode the fraction.

Therefore, the multiplying factor from double is in the range: 2^1023 to 2^-1022. To give an idea how large this is, the scientist estimate there are about 10^80 atoms in universe, in base 2 this is "little" less than 2^266.

Most application only don't work with numbers on this magnitude. And the ones that does, don't care so much about precision.

Let me know if there is something wrong with my logic.

Re: Floating Point Visually Explained (2017)

#99

Earlier quoted context omitted.

Shouldn't i be initialized?

lol, how the compiler didn't warn about uninitialized variable

Compiler warnings are not straightforward and depend on many things; compiler version, optimization settings, warning settings.

  $ gcc-9 -Wuninitialized -O0 float.c  # NO WARNINGS!!!

  $ gcc-9 -O1 float.c  # NO WARNINGS!!!
  
  $ gcc-9 -Wuninitialized -O1 float.c
  float.c: In function 'main':
  float.c:9:5: warning: 'i' is used uninitialized in this function [-Wuninitialized]
      9 |     for (size_t i; i 

Re: Floating Point Visually Explained (2017)

#100

Earlier quoted context omitted.

lol, how the compiler didn't warn about uninitialized variable

Compiler warnings are not straightforward and depend on many things; compiler version, optimization settings, warning settings. $ gcc-9 -Wuninitialized -O0 float.c # NO WARNINGS!!! $ gcc-9 -O1 float.c # NO WARNINGS!!! $ gcc-9 -Wuninitialized -O1 float.c float.c: In function 'main': float.c:9:5: warning: 'i' is used uninitialized in this function [-Wuninitialized] 9 | for (size_t i; i

Weirdly, those two codes behaves differently:

    $ gcc hn.c -O0 -o hn

    for (size_t i; i 
Without break:

    $ gcc hn.c -O0 -o hn

    for (size_t i; i 
Post reply on HN