How can I fix the floating point calculation here?

xuanbao · · 408 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>AFAIK the std lib does not provide any <code>func Round()</code> func in order to fix this issue. I want to get 0.20000000000000000 as a result not 0.20000000000000018. What&#39;s the best way to fix this issue?</p> <p><a href="https://play.golang.org/p/-qzRlXBa_X" rel="nofollow">https://play.golang.org/p/-qzRlXBa_X</a></p> <hr/>**评论:**<br/><br/>qu33ksilver: <pre><p>Wait for 1.10 to be released. Then you can use - <a href="https://tip.golang.org/pkg/math/#Round" rel="nofollow">https://tip.golang.org/pkg/math/#Round</a></p></pre>chmikes: <pre><p>What you see is an error due to the precision limit of floating points. You may change the computation of the value to avoid it, or change the display of the value so that erroneous digits are not shown. </p> <p>To fix the display, use a formatted print. </p> <pre><code>fmt.Printf(&#34;%.15f\n&#34;, r) </code></pre> <p>Adapting the computation depends on your problem.</p> <p>If you want to learn more about floating point computation and become an expert, I would suggest the following document: <a href="http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf" rel="nofollow">http://perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf</a></p></pre>vpol: <pre><p>You can start with reading this. <a href="https://github.com/golang/go/issues/20100" rel="nofollow">https://github.com/golang/go/issues/20100</a></p></pre>kalekold: <pre><p>Right, I&#39;ve read it. ...now what?</p></pre>HowardTheGrum: <pre><p>There is a link at the bottom of it to a Gist that has the source of the function that will be added for the purpose in 1.10. You could use that: <a href="https://play.golang.org/p/2-m5aR0_3T" rel="nofollow">https://play.golang.org/p/2-m5aR0_3T</a></p> <p>But more importantly, you should understand what you are asking of the computer, and what tools you need to use to accomplish what you want. Floats are a very particular animal, and you need to spend some time to understand them, what they can and can&#39;t represent, and what error is being introduced in your calculations. Blindly rounding (at whatever stage of the calculation you intended to do it) is <em>not</em> going to make your answers more correct in general, even though it may seem to help specific cases. </p> <p>If you actually need, for example, precise calculations to a particular number of digits of precision, and you don&#39;t want to actually learn about float&#39;s limitations and how to track the valid precision through calculations, then you pretty much have to use something much slower than floats.</p> <p>That is after all what floats are, a compromise that allows fast floating point calculations to be implemented in hardware without requiring potentially arbitrary amounts of either time or memory. </p> <p>For many, many purposes they are just fine, giving us fast but approximated answers.</p> <p>For certain particular situations, the error in them can explode dramatically, producing wildly different results than naivety would expect. But we find them useful most of the time nonetheless - running Discrete Fast Fourier transforms on audio data, for example, where the error amounts to tiny differences that do not generally detract from the usability of the result, and where a more exact calculation would take so long as to ruin any hope of achieving real-time performance, or in doing perspective transforms on triangles to render 3D graphics, where we need to do multiple millions of triangles per second.</p> <p>But where precision counts - in financial calculations, particularly, where no-one is happy if all the numbers don&#39;t add up in the end, we tend to fall back to something like a Decimal package. For other situations where precision counts, but speed is still required, well, then someone has to sit down and actually work through the calculations with reference to the IEEE standard, and consider how each operation affects the precision of the calculations. Often, this actually involves reworking the math (hey, look, algebra did turn out to be useful in the real world!) to find alternate computations that attain the correct results while moving through a series of calculations that do not disastrously affect the precision.</p> <p>See: <a href="https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html" rel="nofollow">https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html</a> Also: <a href="http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html" rel="nofollow">http://ta.twi.tudelft.nl/users/vuik/wi211/disasters.html</a></p></pre>Killing_Spark: <pre><p>This. </p></pre>icholy: <pre><p>You gotta put it waaaayyy up inside your butt</p></pre>Arnhallr: <pre><p>Thanks ! I will read it now.</p></pre>Arnhallr: <pre><p>I think I found a nice solution to my problem.</p> <pre><code>func Round(x float64, prec int) float64 { if x == 0 { return 0 } if prec &gt;= 0 &amp;&amp; x == math.Trunc(x) { return x } pow := math.Pow10(prec) intermed := x * pow if math.IsInf(intermed, 0) { return x } if x &lt; 0 { x = math.Ceil(intermed - 0.5) } else { x = math.Floor(intermed + 0.5) } if x == 0 { return 0 } return x / pow } </code></pre></pre>earthboundkid: <pre><p>In Go is -0 equal to +0?</p></pre>Arnhallr: <pre><p>Yes.</p></pre>0xjnml: <pre><p>As in math.</p></pre>earthboundkid: <pre><p>Math has nothing on <a href="https://en.wikipedia.org/wiki/IEEE_754" rel="nofollow">https://en.wikipedia.org/wiki/IEEE_754</a></p></pre>WikiTextBot: <pre><p><strong>IEEE 754</strong></p> <p>The IEEE Standard for Floating-Point Arithmetic (IEEE 754) is a technical standard for floating-point computation established in 1985 by the Institute of Electrical and Electronics Engineers (IEEE). The standard addressed many problems found in the diverse floating point implementations that made them difficult to use reliably and portably. Many hardware floating point units now use the IEEE 754 standard.</p> <p>The standard defines:</p> <p>arithmetic formats: sets of binary and decimal floating-point data, which consist of finite numbers (including signed zeros and subnormal numbers), infinities, and special &#34;not a number&#34; values (NaNs)</p> <p>interchange formats: encodings (bit strings) that may be used to exchange floating-point data in an efficient and compact form</p> <p>rounding rules: properties to be satisfied when rounding numbers during arithmetic and conversions</p> <p>operations: arithmetic and other operations (such as trigonometric functions) on arithmetic formats</p> <p>exception handling: indications of exceptional conditions (such as division by zero, overflow, etc.)</p> <p>The current version, IEEE 754-2008 published in August 2008, includes nearly all of the original IEEE 754-1985 standard and the IEEE Standard for Radix-Independent Floating-Point Arithmetic (IEEE 854-1987).</p> <hr/> <p><sup>[</sup> <a href="https://www.reddit.com/message/compose?to=kittens_from_space" rel="nofollow"><sup>PM</sup></a> <sup>|</sup> <a href="https://reddit.com/message/compose?to=WikiTextBot&amp;message=Excludeme&amp;subject=Excludeme" rel="nofollow"><sup>Exclude</sup> <sup>me</sup></a> <sup>|</sup> <a href="https://np.reddit.com/r/golang/about/banned" rel="nofollow"><sup>Exclude</sup> <sup>from</sup> <sup>subreddit</sup></a> <sup>|</sup> <a href="https://np.reddit.com/r/WikiTextBot/wiki/index" rel="nofollow"><sup>FAQ</sup> <sup>/</sup> <sup>Information</sup></a> <sup>|</sup> <a href="https://github.com/kittenswolf/WikiTextBot" rel="nofollow"><sup>Source</sup></a> <sup>|</sup> <a href="https://www.reddit.com/r/WikiTextBot/wiki/donate" rel="nofollow"><sup>Donate</sup></a> <sup>]</sup> <sup>Downvote</sup> <sup>to</sup> <sup>remove</sup> <sup>|</sup> <sup>v0.28</sup></p></pre>0xjnml: <pre><p>Quite the opposite. IEEE754 was free to specify whatever. But it&#39;s math where -0 and +0 is always just the same and only one real number.</p></pre>slushmaker: <pre><p><a href="https://github.com/shopspring/decimal" rel="nofollow">https://github.com/shopspring/decimal</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

408 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传