{"id":937,"date":"2009-08-10T16:00:36","date_gmt":"2009-08-11T00:00:36","guid":{"rendered":"https:\/\/www.reenigne.org\/blog\/?p=937"},"modified":"2009-07-19T20:10:36","modified_gmt":"2009-07-20T04:10:36","slug":"floating-point-is-not-evil","status":"publish","type":"post","link":"https:\/\/www.reenigne.org\/blog\/floating-point-is-not-evil\/","title":{"rendered":"Floating point is not evil"},"content":{"rendered":"<p>In response to <a href=\"http:\/\/compaspascal.blogspot.com\/2009\/06\/floating-point-values-are-evil.html\">this<\/a>:<\/p>\n<p>Floating point is not evil and it is deterministic, but you need to know what the values you&#8217;re working with actually are. Basically, floating point is like scientific notation, except with 2s instead of 10s. In other words, instead storing numbers like 1.234*10<sup>4<\/sup> it stores numbers like 1.0011010010<sub>2<\/sub>*2<sup>10<\/sup>. It&#8217;s actually stored as a pair of numbers, a mantissa and an exponent. The number of bits in the mantissa is fixed (it&#8217;s 23 bits for single precision and 52 for double) and the leading &#8220;1&#8221; is implied. Each number representable as an IEEE floating point constant has exactly one representation except for zero (+0 and -0 have different bit patterns for complicated reasons). There are complications (denormals, NaNs and infinities) which can usually be ignored and which I won&#8217;t go into.<\/p>\n<p>Floating point numbers are handy for lots of purposes but they do have a couple of problems.<\/p>\n<p>The first problem is that floating point numbers are inefficient. They are very quick with today&#8217;s hardware but consider what you&#8217;d do if neither floating point hardware nor floating point libraries were available. For most applications, you&#8217;d use fixed point numbers &#8211; you&#8217;d store an integer and it would be implied by the type of number you&#8217;re working with that the actual numeric value is obtained by dividing this integer value by 2<sup>n<\/sup> for some n. For most purposes you probably wouldn&#8217;t store that n with each integer &#8211; all your numbers have the same number of significant digits. For example, if you&#8217;re writing a graphics program you might decide that units of 1\/256 of a pixel width are always enough, so n would always be -8. When writing floating-point programs, most programmers don&#8217;t do this calculation to figure out what the precision needs to be, they just use single precision floating point or switch to double if that isn&#8217;t precise enough. While constant precision is preferable for a general purpose calculator, most actual applications are better served by constant resolution.<\/p>\n<p>The other problem is that sooner or later you&#8217;ll run out of precision. If you&#8217;re plotting Mandelbrot sets, sooner or later you&#8217;ll zoom in far enough that adjacent pixels have complex numbers with the same floating-point representation. If you&#8217;re using FFTs to multiply big integers, sooner or later you&#8217;ll want to multiply integers so large that floating-point numbers won&#8217;t have sufficient precision. If you&#8217;re using hardware floating point, this is quite difficult to solve (you need to find or write a big-float library) and will cause a big speed hit, so most people will give up at that point. However, if you&#8217;re already using fixed point bignums, it&#8217;s just a question of adding another digit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In response to this: Floating point is not evil and it is deterministic, but you need to know what the values you&#8217;re working with actually are. Basically, floating point is like scientific notation, except with 2s instead of 10s. In other words, instead storing numbers like 1.234*104 it stores numbers like 1.00110100102*210. It&#8217;s actually stored [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[4],"tags":[],"class_list":["post-937","post","type-post","status-publish","format-standard","hentry","category-computer"],"_links":{"self":[{"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/posts\/937","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/comments?post=937"}],"version-history":[{"count":1,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/posts\/937\/revisions"}],"predecessor-version":[{"id":938,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/posts\/937\/revisions\/938"}],"wp:attachment":[{"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/media?parent=937"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/categories?post=937"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.reenigne.org\/blog\/wp-json\/wp\/v2\/tags?post=937"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}