Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 数值编程语言是否区分“a”;“最大有限数”;及;无穷大;?_Python_Matlab_Numpy_Integer Overflow - Fatal编程技术网

Python 数值编程语言是否区分“a”;“最大有限数”;及;无穷大;?

Python 数值编程语言是否区分“a”;“最大有限数”;及;无穷大;?,python,matlab,numpy,integer-overflow,Python,Matlab,Numpy,Integer Overflow,问题动机: 在我所了解的标准数值语言中(例如,Matlab、Python numpy等),例如,如果取一个适度大的数字的指数,则由于数值溢出,输出为无穷大。如果乘以0,则得到NaN。单独来说,这些步骤是合理的,但它们揭示了数学实现中的逻辑错误。由溢出产生的第一个数是有限的,我们显然希望0与这个大的有限数相乘的结果是0 明确地: >>> import numpy as np >>> np.exp(709)*0 0.0 >>> np.exp(71

问题动机:

在我所了解的标准数值语言中(例如,Matlab、Python numpy等),例如,如果取一个适度大的数字的指数,则由于数值溢出,输出为无穷大。如果乘以0,则得到NaN。单独来说,这些步骤是合理的,但它们揭示了数学实现中的逻辑错误。由溢出产生的第一个数是有限的,我们显然希望0与这个大的有限数相乘的结果是0

明确地:

>>> import numpy as np
>>> np.exp(709)*0
0.0
>>> np.exp(710)*0
nan
我想我们可以在这里引入“最大有限值”(LFV)的概念,它将具有以下特性:

  • LFV将是数值溢出的默认值,否则 四舍五入到无穷大
  • LFV<无穷大
  • 任何显式数字(MATLAB详细信息:realmax
  • LFV*0=0
另一方面,不应以LFV描述的方式简单地重新定义无穷大。它对于0*无穷大=0没有意义…适当地,无穷大的当前标准实现在此设置中产生NaN。此外,有时需要将数字初始化为无穷大,并且您希望得到任何数字运算的结果离子,甚至是产生LFV严格小于初始化值的离子(这对于某些逻辑语句来说是方便的)。我确信在其他情况下存在适当的无穷大是必要的——我的观点是,无穷大应该而不是简单地重新定义为具有上述LFV属性

问题:

我想知道是否有任何语言使用这样的方案,以及这样的方案是否存在任何问题。这个问题在适当的数学中不会出现,因为数字大小没有这些数字限制,但我认为在编程语言中实现一致的数学时,这是一个真正的问题。本质上,对于LFV,我想我想要一个最大显式值和无穷大LFV=(LEV,无穷大)之间的开放区间的简写,但是这个直觉可能是错误的


更新:在评论中,人们似乎有点反对我提出的问题的实用性。我的问题不是因为出现了许多相关问题,而是因为同一问题在许多不同的环境中经常出现。与进行数据分析的人交谈时,这往往会对运行时间产生影响训练/拟合模型时出错。问题基本上是为什么不使用数字语言处理。从评论中,我基本上得出结论,编写语言的人没有看到以这种方式处理问题的实用性。在我看来,当某些特定问题频繁发生时,对于使用某种语言的人来说,这是非常重要的以一种有原则的方式处理这些异常可能是有意义的,这样每个用户就不必这样做了。

所以…我很好奇,四处搜寻了一下

正如我在评论中已经提到的,“最大有限值”IEEE 754中存在的一种类型,如果考虑了溢出标志设置的无穷大值,则对应于所建议的LFV,区别在于该标志仅可在操作之后被读出,而不是作为值本身的一部分被存储。这意味着如果发生溢出,则必须手动检查标志并采取行动。而不仅仅是内置LFV*0=0

关于异常处理及其在编程语言中的支持,有一个非常有趣的话题。引用:

IEEE 754设置标志并返回无穷大或安静NaN的模型假设用户经常(或至少适当地)测试状态诊断原始问题需要用户检查所有结果是否存在异常值,而异常值反过来又假设这些结果在所有操作中都会被过滤,因此可以标记错误数据。根据这些假设,一切都应该正常,但不幸的是,它们并不十分现实

论文还抱怨对浮点异常处理的支持较差,特别是在C99和Java中(我相信大多数其他语言也不比这更好)。尽管如此,没有做出重大努力来解决这一问题或创建更好的标准,在我看来,似乎表明IEEE 754及其支持在某种意义上“足够好”(稍后将详细介绍)


让我为您的示例问题提供一个解决方案来演示一些东西。我使用numpy使其在溢出时引发异常:

import numpy as np

def exp_then_mult_naive(a, b):
    err = np.seterr(all='ignore')
    x = np.exp(a) * b
    np.seterr(**err)
    return x

def exp_then_mult_check_zero(a, b):
    err = np.seterr(all='ignore', over='raise')
    try:
        x = np.exp(a)
        return x * b
    except FloatingPointError:
        if b == 0:
            return 0
        else:
            return exp_then_mult_naive(a, b)
    finally:
        np.seterr(**err)

def exp_then_mult_scaling(a, b):
    err = np.seterr(all='ignore', over='raise')
    e = np.exp(1)
    while abs(b) < 1:
        try:
            x = np.exp(a) * b
            break
        except FloatingPointError:
            a -= 1
            b *= e
    else:
        x = exp_then_mult_naive(a, b)
    np.seterr(**err)
    return x

large = np.float_(710)
tiny = np.float_(0.01)
zero = np.float_(0.0)

print('naive: e**710 * 0 = {}'.format(exp_then_mult_naive(large, zero)))
print('check zero: e**710 * 0 = {}'
    .format(exp_then_mult_check_zero(large, zero)))
print('check zero: e**710 * 0.01 = {}'
    .format(exp_then_mult_check_zero(large, tiny)))
print('scaling: e**710 * 0.01 = {}'.format(exp_then_mult_scaling(large, tiny)))

# output:
# naive: e**710 * 0 = nan
# check zero: e**710 * 0 = 0
# check zero: e**710 * 0.01 = inf
# scaling: e**710 * 0.01 = 2.233994766161711e+306
将numpy导入为np
def exp_then_mult_naive(a,b):
err=np.seterr(all='ignore')
x=np.exp(a)*b
np.seterr(**错误)
返回x
def exp然后检查零(a,b):
err=np.seterr(all='ignore',over='raise')
尝试:
x=np.exp(a)
返回x*b
除了FloatingPointError:
如果b==0:
返回0
其他:
返回exp\u then\u mult\u naive(a,b)
最后:
np.seterr(**错误)
def exp_然后_mult_缩放(a,b):
err=np.seterr(all='ignore',over='raise')
e=np.exp(1)
当abs(b)<1时:
尝试:
x=np.exp(a)*b
打破
除了FloatingPointError:
a-=1
b*=e
其他:
x=exp\u then\u mult\u naive(a,b)
np.seterr(**错误)
返回x
大=np.浮点数(710)
微小=np.浮动(0.01)
零=np.浮点(0.0)
打印('naive:e**710*0={}'。格式(exp\u then\u mult\u naive(大,零)))
打印('检查零:e**710*0={}'
.format(exp\u then\u mult\u check\u zero(大,零)))
打印('检查零:e**710*0.01={}'
.format(exp\u then\u mult\u check\u zero(大,小)))
打印('scaling:e**710*0.01={}'。格式(exp\u-then\u-mult\u scaling(大、小)))
#输出:
#天真的: