如何避免浮点错误? [英] How to avoid floating point errors?

查看:175
本文介绍了如何避免浮点错误?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图编写一个近似平方根的函数(我知道这里有数学模块,我自己也想这样做),而且我被浮点算术搞砸了。如何避免这种情况?

  def sqrt(num):
root = 0.0
while root *根<
root + = 0.01
return root



 >>> sqrt(4)
2.0000000000000013
>>> sqrt(9)
3.00999999999998

我意识到我可以使用 round(),但我希望能够做到这一点非常准确。我希望能够计算出6或7位数字。如果我四舍五入,这是不可能的。我想了解如何正确处理Python中的浮点计算。

解决方案

这实际上与Python无关 - d使用硬件的二进制浮点算法,以任何语言查看相同的行为。首先阅读文档



之后阅读一下,你会更好地理解你是不是在你的代码中添加一百分之一。这正是您要添加的内容:

 >>> from decimal import Decimal 
>>>十进制(.01)
十进制('0.01000000000000000020816681711721685132943093776702880859375')

二进制浮点值(C中的双精度)近似于精确的十进制值0.01。你真正添加的东西比1/100大一些。



控制浮点数字错误是被称为数值分析的字段,大而复杂的话题。只要你被浮动只是十进制值的近似值所震惊,使用十进制模块。这会为你带来一个浅的世界。例如,给你的函数做这个小的修改:

 从十进制数导入十进制数作为D 

def sqrt(num):
root = D(0)
,而root * root<















$ b $那么:

 >>> sqrt(4)
十进制('2.00')
>>> sqrt(9)
十进制('3.00')

实际上并不准确,在简单的例子中可能并不令人吃惊,因为现在它正好加上一百分之一。另外一种方法是坚持使用浮动并添加一些东西 完全可以表示为二进制浮点形式: I / 2 ** J 形式的值。例如,不是加0.01,而是加0.125(1/8)或0.0625(1/16)。然后查找牛顿法来计算平方根; - )

I was trying to write a function to approximate square roots (I know there's the math module...I want to do it myself), and I was getting screwed over by the floating point arithmetic. How can you avoid that?

def sqrt(num):
    root = 0.0
    while root * root < num:
        root += 0.01
    return root

Using this has these results:

>>> sqrt(4)
2.0000000000000013
>>> sqrt(9)
3.00999999999998

I realize I could just use round(), but I want to be able to make this really accurate. I want to be able to calculate out to 6 or 7 digits. That wouldn't be possible if I'm rounding. I want to understand how to properly handle floating point calculations in Python.

解决方案

This really has nothing to do with Python - you'd see the same behavior in any language using your hardware's binary floating-point arithmetic. First read the docs.

After you read that, you'll better understand that you're not adding one one-hundredth in your code. This is exactly what you're adding:

>>> from decimal import Decimal
>>> Decimal(.01)
Decimal('0.01000000000000000020816681711721685132943093776702880859375')

That string shows the exact decimal value of the binary floating ("double precision" in C) approximation to the exact decimal value 0.01. The thing you're really adding is a little bigger than 1/100.

Controlling floating-point numeric errors is the field called "numerical analysis", and is a very large and complex topic. So long as you're startled by the fact that floats are just approximations to decimal values, use the decimal module. That will take away a world of "shallow" problems for you. For example, given this small modification to your function:

from decimal import Decimal as D

def sqrt(num):
    root = D(0)
    while root * root < num:
        root += D("0.01")
    return root

then:

>>> sqrt(4)
Decimal('2.00')
>>> sqrt(9)
Decimal('3.00')

It's not really more accurate, but may be less surprising in simple examples because now it's adding exactly one one-hundredth.

An alternative is to stick to floats and add something that is exactly representable as a binary float: values of the form I/2**J. For example, instead of adding 0.01, add 0.125 (1/8) or 0.0625 (1/16).

Then look up "Newton's method" for computing square roots ;-)

这篇关于如何避免浮点错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆