TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

0.1 and 0.2 Returns 0.30000000000000004 (2018)

58 点作者 tingabing大约 4 年前

34 条评论

crazygringo大约 4 年前
Indeed, and therefore:<p><pre><code> 0.1 + 0.2 != 0.3 </code></pre> You can check it in the JavaScript console.<p>This actually makes me wonder if anyone&#x27;s ever attempted a floating-point representation that <i>builds in an error range</i>, and correctly propagated&#x2F;amplified error over operations.<p>E.g. a simple operation like &quot;1 &#x2F; 10&quot; (to generate 0.1) would be stored not as a single floating-point value, but really as the <i>range</i> between the closest representation greater than and less than it. The same with &quot;2 &#x2F; 10&quot;, and then when asking if 0.1 + 0.2 == 0.3, it would find an <i>overlap in ranges</i> between the left-hand and right-hand sides and return <i>true</i>. Every floating-point operation would then take and return these ranges.<p>Then floating point arithmetic could be used to actually reliably test equality without ever generating false negatives. And if you examined the result of calculation of 10,000 operations, you&#x27;d also be able to get a sense of how off it might maximally be.<p>I&#x27;ve search online and can&#x27;t find anything like it, though maybe I&#x27;m missing an important keyword.
评论 #26773342 未加载
评论 #26773335 未加载
评论 #26773336 未加载
评论 #26774297 未加载
评论 #26773318 未加载
评论 #26773363 未加载
评论 #26773853 未加载
dang大约 4 年前
Related past threads (not about this article):<p><i>0.30000000000000004</i> - <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=21686264" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=21686264</a> - Dec 2019 (402 comments)<p><i>0.30000000000000004</i> - <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14018450" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=14018450</a> - April 2017 (130 comments)<p><i>0.30000000000000004</i> - <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=10558871" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=10558871</a> - Nov 2015 (240 comments)<p><i>0.30000000000000004</i> - <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=1846926" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=1846926</a> - Oct 2010 (128 comments)<p>Resisting temptation to list floating-point math threads because there are so many:<p><a href="https:&#x2F;&#x2F;hn.algolia.com&#x2F;?dateRange=all&amp;page=0&amp;prefix=true&amp;query=floating%20point%20comments%3E20&amp;sort=byDate&amp;type=story&amp;storyText=none" rel="nofollow">https:&#x2F;&#x2F;hn.algolia.com&#x2F;?dateRange=all&amp;page=0&amp;prefix=true&amp;que...</a>
kazinator大约 4 年前
This just has to do with printing.<p><pre><code> This is the TXR Lisp interactive listener of TXR 256. Quit with :quit or Ctrl-D on an empty line. Ctrl-X ? for cheatsheet. TXR works even if the application surface is not free of dirt and grease. 1&gt; (+ 0.1 0.2) 0.3 </code></pre> OK, so then:<p><pre><code> 2&gt; (set *print-flo-precision* 17) 17 3&gt; (+ 0.1 0.2) 0.30000000000000004 </code></pre> But:<p><pre><code> 4&gt; 0.1 0.10000000000000001 5&gt; 0.2 0.20000000000000001 6&gt; 0.3 0.29999999999999999 </code></pre> I.e. 0.1 isn&#x27;t exactly 0.1 and 0.2 isn&#x27;t exactly 0.2 in the first place! The misleading action is to compare the <i>input</i> notation of 0.1 and 0.2 to the <i>printed output</i> of the sum, rather than consistently compare nothing but values printed using the same precision.<p>The IEEE double format can store 15 decimal digits of precision such that all those decimal digits are recoverable. If we print values to no more than 15 digits, then things look &quot;artificially clean&quot; for situations like (+ 0.1 0.2).<p>I made *print-flo-precision* have an initial value of 15 for this reason.<p>The 64 bit double gives us 0.1, 0.2 and 0.3 to 15 digits of precision. If we round at that many digits, we don&#x27;t see the trailing junk of representational error.<p>Unfortunately, to 15 digits of precision, the data type gives us two different 0.3&#x27;s: the 0.299999... one and the 0.3.....04 one. Thus:<p><pre><code> 7&gt; (= (+ 0.1 0.2) 0.3) nil </code></pre> That&#x27;s the real kicker; not so much the printing. This representational issue bites you regardless of what precision you print with and is the reason why there are situations in which you cannot compare floating-point values exactly.
评论 #26773406 未加载
kungito大约 4 年前
HN is more and more like first semester coding class where the professor always tells the &quot;fun facts&quot; but we have to be in the same class every year
评论 #26776368 未加载
评论 #26773822 未加载
评论 #26773951 未加载
评论 #26773982 未加载
hprotagonist大约 4 年前
It sure does: <a href="https:&#x2F;&#x2F;0.30000000000000004.com&#x2F;" rel="nofollow">https:&#x2F;&#x2F;0.30000000000000004.com&#x2F;</a>
评论 #26773368 未加载
评论 #26773190 未加载
neilv大约 4 年前
One of the many reasons I think we all would&#x27;ve been better off, had Brendan Eich decided he&#x27;d been able to simply use Scheme within the crazy time constraint he&#x27;d been given, rather than create JavaScript, :) is that Scheme comes with a distinction between exact and inexact numbers, in its numerical tower:<p><a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Numerical_tower" rel="nofollow">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Numerical_tower</a><p>One change I&#x27;d consider making to Scheme, and to most high-level general-purpose languages (that aren&#x27;t specialized for number-crunching or systems programming), is to have the reader default to reading numeric literals as exact.<p>For example, the current behavior in Racket and Guile:<p><pre><code> Welcome to Racket v7.3. &gt; (+ 0.1 0.2) 0.30000000000000004 &gt; (+ #e0.1 #e0.2) 3&#x2F;10 &gt; (exact-&gt;inexact (+ #e0.1 #e0.2)) 0.3 </code></pre> So, I&#x27;d lean towards getting the `#e` behavior without needing the `#e` in the source.<p>By default, that would give the programmer in this high-level language the expected behavior.<p>And systems programmers, people writing number-crunching code, would be able to add annotations when they want an imprecise float or an overflowable int.<p>(I&#x27;d also default to displaying exact fractional rational numbers using familiar decimal point conventions, not the fractional form in the example above.)
评论 #26774225 未加载
评论 #26784708 未加载
评论 #26774139 未加载
评论 #26774096 未加载
cratermoon大约 4 年前
If you think <i>that</i> is crazy, check out Muller&#x27;s Recurrence: <a href="https:&#x2F;&#x2F;scipython.com&#x2F;blog&#x2F;mullers-recurrence&#x2F;" rel="nofollow">https:&#x2F;&#x2F;scipython.com&#x2F;blog&#x2F;mullers-recurrence&#x2F;</a>
georgeburdell大约 4 年前
I use this as one of my interview questions (in a piece of code where it would run correctly if 0.1 + 0.2 = 0.3). Maybe 1&#x2F;3 of interviewees recognize the cause, and maybe half of those can actually explain why and how to mitigate it. I work in scientific computing so it&#x27;s absolutely relevant to my work
arduinomancer大约 4 年前
Does this mean I could write a calculator in JavaScript which is more accurate than the language but not as fast?<p>For example: just treat numbers as strings and write code that adds the digits one by one and does the right carries<p>Now that I think about it, is this the whole point of the Java BigDecimal class?
评论 #26773723 未加载
评论 #26773392 未加载
评论 #26773311 未加载
bluenose69大约 4 年前
In R, there are functions for practical equality (to within a tolerance that makes sense on the local machine), e.g.<p><pre><code> &gt; all.equal(0.1+0.2,0.3) [1] TRUE </code></pre> and functions for actual equality, e.g.<p><pre><code> &gt; identical(0.1+0.2,0.3) [1] FALSE</code></pre>
评论 #26774435 未加载
PaulHoule大约 4 年前
<a href="https:&#x2F;&#x2F;www.crockford.com&#x2F;dec64.html" rel="nofollow">https:&#x2F;&#x2F;www.crockford.com&#x2F;dec64.html</a><p>and see me in the morning.
lelf大约 4 年前
<p><pre><code> Coq &lt; Compute 0.1. Toplevel input, characters 8-11: &gt; Compute 0.1. &gt; ^^^ Warning: The constant 0.1 is not a binary64 floating-point value. A closest value 0x1.999999999999ap-4 will be used and unambiguously printed 0.10000000000000001. [inexact-float,parsing] = 0.10000000000000001 : float</code></pre>
globular-toast大约 4 年前
Was the title of this post automatically generated? Why did it turn &quot;0.1 + 0.2&quot; into &quot;0.1 and 0.2&quot;?
RcouF1uZ4gsC大约 4 年前
This is pretty much the same problem as what does 1&#x2F;3 + 1&#x2F;3 = in decimal. You are specifying fractions that don’t have an exact finite representation in that base (base 10 with 1&#x2F;3) and (base 2 with 0.1 or 1&#x2F;10).<p>With proper rounding and I&#x2F;O these are not generally an issue.
dec0dedab0de大约 4 年前
I think high level languages shouldn&#x27;t even have floats, unless they&#x27;re a special type for doing floating point math.<p>Specifically I&#x27;m thinking about python, the literal x.x should be for Decimal and float should have to be imported to be used as an optimization if you need it.
zamadatix大约 4 年前
I&#x27;ve seen a lot of stuff on getting the shortest representation that is equal to the floating point value back but what about finding the minimum&#x2F;maximum representation that is equal to a given value?
评论 #26773304 未加载
29athrowaway大约 4 年前
Do it in Python and many other languages you&#x27;ll get the same result.<p><pre><code> &gt;&gt;&gt; 0.1 + 0.2 0.30000000000000004 </code></pre> That&#x27;s the expected behavior of floating-point numbers, more specifically, IEEE 754.<p>If you don&#x27;t want this to happen, use fixed-point numbers, if they&#x27;re supported by your language, or integers with a shifted decimal point.<p>Personally, I think if you don&#x27;t know this, it&#x27;s not safe for you to write computer programs professionally, because this can have real consequences when dealing with currency.
lossolo大约 4 年前
If anyone would like to know more then read this paper from 1991 by David Goldberg <i>What every computer scientist should know about floating-point arithmetic</i>, very accessible content even if you are not from CS field.<p><a href="http:&#x2F;&#x2F;pages.cs.wisc.edu&#x2F;~david&#x2F;courses&#x2F;cs552&#x2F;S12&#x2F;handouts&#x2F;goldberg-floating-point.pdf" rel="nofollow">http:&#x2F;&#x2F;pages.cs.wisc.edu&#x2F;~david&#x2F;courses&#x2F;cs552&#x2F;S12&#x2F;handouts&#x2F;g...</a>
wodenokoto大约 4 年前
In python, 0.3 prints as 0.3, but it&#x27;s a double, so it should be 0.299999999999999988897769753748434595763683319091796875 (according to the article, and the 0.1+0.2 != 0.3 trick also works)<p>What controls this rounding?<p>e.g., in an interactive python prompt i get:<p><pre><code> &gt;&gt;&gt; b = 0.299999999999999988897769753748434595763683319091796875 &gt;&gt;&gt; b 0.3</code></pre>
评论 #26773526 未加载
评论 #26773434 未加载
OskarS大约 4 年前
Not in Raku it doesn&#x27;t!<p><pre><code> &gt; 1.1 + 2.2 3.3 &gt; 1.1 + 2.2 == 3.3 True </code></pre> EDIT: to be clear: this is not because Raku is magic, it&#x27;s because Raku defaults to a rational number type for decimal literals, which is arguably a much better choice for a language like Raku.
评论 #26773252 未加载
评论 #26773180 未加载
评论 #26773270 未加载
tmabraham大约 4 年前
<a href="https:&#x2F;&#x2F;twitter.com&#x2F;qntm&#x2F;status&#x2F;1381346718919356416" rel="nofollow">https:&#x2F;&#x2F;twitter.com&#x2F;qntm&#x2F;status&#x2F;1381346718919356416</a> Hahahaha!
gravelc大约 4 年前
As an aside, just finish qntm&#x27;s spectacularly good &#x27;There Is No Antimemetics Division&quot;. Highly worth a read if you&#x27;re after some highly original sci-fi.
bassdropvroom大约 4 年前
Super interesting. I&#x27;d noticed this behaviour previously, but never knew how or why this was the case (and not really bothered to search for it either). Thanks!
worik大约 4 年前
Golly. Surprised by floating point arithmetic?<p>1.99999999.... == 2.0<p>There are limits to computer representation of floating point numbers. Computers are finite state, floating point numbers are not.<p>sigh
评论 #26773612 未加载
评论 #26773422 未加载
hnjst大约 4 年前
I guess that can be tracked back to the use of fancy new buggy tools ;)<p>bc &lt;&lt;&lt; &quot;0.1 + 0.2&quot;<p>.3<p>bc &lt;&lt;&lt; &quot;1.0E4096 +1 -1.0E4096&quot;<p>1.000000<p>node -e &quot;console.log(1.0E128 +1 -1.0E128)&quot;<p>0<p>python -c &quot;print(1.0E128 +1 -1.0E128)&quot;<p>0.0
kissgyorgy大约 4 年前
<a href="https:&#x2F;&#x2F;floating-point-gui.de&#x2F;" rel="nofollow">https:&#x2F;&#x2F;floating-point-gui.de&#x2F;</a>
IncRnd大约 4 年前
This is why games and certain other types of coding use fixed point arithmetic.
phoe-krk大约 4 年前
[2018]
lamontcg大约 4 年前
Your monthly HackerNews reminder that machine epsilon is a thing.
IEEE754大约 4 年前
&gt; does not interpret the 0.1 as the real number<p>The focus should be on _rational_ numbers. This particular example is all about representation error - precision is implicated, but not the cause.<p>Ignore precision for a second: The inputs 0.1 and 0.2 are intended to be _rational_. This means they can be accurately represented finitely (unlike an irrational number like PI). Now when using <i>fractions</i> they can _always_ be accurately represented finitely in <i>any</i> base:<p><pre><code> 1&#x2F;10= base 10: 1&#x2F;10 base 2: 1&#x2F;1010 2&#x2F;10= base 10: 2&#x2F;10 base 2: 10&#x2F;1010 </code></pre> The neat thing about rationals, is that when using the four basic arithmetic operations: two rational inputs will always produce one rational output :) this is relevant: 1&#x2F;10 and 2&#x2F;10 are both rationals, there is no fundamental reason that addition cannot produce 3&#x2F;10. When using a format that has no representation error (i.e fractions) the output will be rational for all rational inputs (given enough precision, which is not a realistic issue in this case). When we add these particular numbers in our heads however, almost everyone uses decimals (base 10 floating point), and in <i>this particular case</i> that doesn&#x27;t cause a problem, but what about 1&#x2F;3?<p>This is the key: rationals cannot always be represented finitely in floating point formats, but this is merely an artifact of the format and the base. Different bases have different capabilities:<p><pre><code> 1&#x2F;10= base 10: 0.1 base 2: 0.00011001100110011r 2&#x2F;10= base 10: 0.2 base 2: 0.00110011001100110r 1&#x2F;3= base 10: 0.33333333333333333r base 2: 0.01010101010101010r </code></pre> IEEE754 format is a bit more complicated than above, but this is sufficient to make the point.<p>If you can grok that key point (representation error), here&#x27;s the real understanding of this problem:<p>Deception 1: The parser has to convert &#x27;0.1&#x27; decimal into base 2, which will cause the periodic significand &#x27;1001100110011&#x27; (not accurately stored at any precision)... yet when you ask for it back, the formater magically converts it to &#x27;0.1&#x27; why? because the parser and formater have symmetrical error :) This is kinda deceptive, because it makes it look like storage is accurate if you don&#x27;t know what&#x27;s going on under the hood.<p>Deception 2: Many combinations of arithmetic on simple rational decimal inputs also have rational outputs from the formatter, which furthers the illusion. For example, nether 0.1 or 0.3 are representable in base 2, yet 0.1 + 0.3 will be <i>formatted</i> to &#x27;0.4&#x27; why? It just happens that the arithmetic on those inaccurate representations added up to the same error that the parser produces when parsing &#x27;0.4&#x27;, and since the parser and formatter produce symmetric error, the output is a rational decimal.<p>Deception 3: Most of us grew up with calculators, or even software calculator programs. All of these usually round display values to 10 significant decimals by default, which is quite a bit less than the max decimal output of a double. This always conceals any small representation errors output by the formatter after arithmetic on rational decimal inputs - which makes calculators look infallible when doing simple math.
selcuka大约 4 年前
Obligatory SMBC [1] and xkcd [2]:<p>[1] <a href="https:&#x2F;&#x2F;www.smbc-comics.com&#x2F;?id=2999" rel="nofollow">https:&#x2F;&#x2F;www.smbc-comics.com&#x2F;?id=2999</a><p>[2] <a href="https:&#x2F;&#x2F;xkcd.com&#x2F;2170&#x2F;" rel="nofollow">https:&#x2F;&#x2F;xkcd.com&#x2F;2170&#x2F;</a>
Black101大约 4 年前
its ok... there are bigger mistakes&#x2F;bugs at stock brokers
The_rationalist大约 4 年前
The problem is solved in many languages such as Java by suffixing F to the numbers.
arnon大约 4 年前
Floating point considered harmful<p>Edit: this is not a blanket statement. It was meant in the context.
评论 #26773174 未加载
评论 #26773394 未加载
评论 #26773105 未加载
评论 #26773298 未加载