首页 » PHP教程 » phpfloatnan技巧_Python 中神奇的两种浮点数nan 和 inf

phpfloatnan技巧_Python 中神奇的两种浮点数nan 和 inf

访客 2024-12-08 0

扫一扫用手机浏览

文章目录 [+]

它提到的部分问题,读者们可以先思考下:

若两个元组相等,即 a==b 且 a is b,那么相同索引的元素(如 a[0] 、b[0])是否一定相等呢?若两个工具的 hash 结果相等,即 hash(a) == hash(b),那么它们是否一定相等呢?

答案当然都为否(不然就不叫冷知识了),大家可以先考试测验回答一下,然后再往下看。

phpfloatnan技巧_Python 中神奇的两种浮点数nan 和 inf

-----思考分割线-----

phpfloatnan技巧_Python 中神奇的两种浮点数nan 和 inf
(图片来自网络侵删)

好了,先来看看第一个问题。
两个相同的元组 a、b,它们有如下的关系:

>>> a = (float('nan'),)>>> b = a>>> a # (nan,)>>> b # (nan,)>>> type(a), type(b)(<type 'tuple'>, <type 'tuple'>)>>> a == bTrue>>> a is b # 即 id(a) == id(b)True>>> a[0] == b[0]False

以上代码表明:a 即是 b(类型、值与 id 都相等),但是它们的对位元素却不相等。

两个元组都只有一个元素(逗号后面没有别的元素,这是单元素的元组的表示方法,即 len(a)==1 )。
float() 是个内置函数,可以将入参布局成一个浮点数。

为什么会这样呢?先查阅一下文档,这个内置函数的解析规则是:

sign ::= \公众+\"大众 | \公众-\"大众infinity ::= \"大众Infinity\"大众 | \"大众inf\"大众nan ::= \公众nan\"大众numeric_value ::= floatnumber | infinity | nannumeric_string ::= [sign] numeric_value

它在解析时,可以解析前后的空格、前缀的加减号(+/-)、浮点数,除此之外,还可以解析两类字符串(不区分大小写):\公众Infinity\"大众或\"大众inf\"大众,表示无穷大数;“nan”,表示不是数(not-a-number),确切地说,指的是除了数以外的所有东西。

前面分享的第一个冷知识就跟“nan”有关,作为整体,两个元组相等,但是它们唯一的元素却不相等。
之以是会这样,由于“nan”表示除了数以外的东西,它是一个范围,以是不可比较。

作为比拟,我们来看看两个“无穷大的浮点数”是什么结果:

>>> a = (float('inf'),)>>> b = a>>> a # (inf,)>>> b # (inf,)>>> a == b # True>>> a is b # True>>> a[0] == b[0] # True

把稳末了一次比较,它跟前面的两个元组恰好相反,由此,我们可以得出结论:两个无穷大的浮点数,数值相等,而两个“不是数的东西”,数值不相等。

化简一下,可以这样看:

>>> a = float('inf')>>> b = float('inf')>>> c = float('nan')>>> d = float('nan')>>> a == b # True>>> c == d # False

以上便是第一个冷知识的揭秘。
接着看第二个:

>>> hash(float('nan')) == hash(float('nan'))True

前面刚说了两个“不是数的东西”不相等,这里却显示它们的哈希结果相等,这挺违背常理的。

我们可以推理出一条大略的结论:不相等的两个工具,其哈希结果可能相等。

缘故原由在于,hash(float('nan')) 的结果即是 0,它是个固定值,作比较时当然就相等了。

实在,关于 hash() 函数,还埋了一个彩蛋:

>>> hash(float('inf')) # 314159>>> hash(float('-inf')) # -314159

有没有以为这个数值很熟习啊?它正是圆周率的前五位 3.14159,去除小数点后的结果。
在早期的 Python 版本中,负无穷大数的哈希结果实在是 -271828,正是取自于自然对数 e。
这两个数都是硬编码在 Python 阐明器中的,算是某种致敬吧。

由于 float('nan') 的哈希值相等,这常日意味着它们不可以作为字典的不同键值,但是事实却出人意料:

>>> a = {float('nan'): 1, float('nan'): 2}>>> a{nan: 1, nan: 2}# 作为比拟:>>> b = {float('inf'): 1, float('inf'): 2}>>> b{inf: 2}

如上所示,两个 nan 键值在表示上千篇一律(把稳,它们没有用引号括起来),它们可以共存,而 inf 却只能归并成一个,再次展示出了 nan 的神奇。

好了,两个很冷的小知识分享完毕,背后的缘故原由都在于 float() 取浮点数时,Python 许可了 nan(不是数)的存在,它表示不确切的存在,以是导致了这些奇怪的结果。

末了,我们作下小结:

包含 float('nan') 的两个元组,当做整体作比较时,结果相等;两个相等的元组,其对位的元素可能不相等float('nan') 表示一个“不是数”的东西,它本身不是确定值,两个工具作比较时不相等,但是其哈希结果是固定值,作比较时相等;可用作字典的键值,而且是不冲突的键值float('inf') 表示一个无穷大的浮点数,可看作确定的值,两个工具做比较时相等,其哈希结果也相等;可用作字典的键值,但是会产生冲突float('nan') 的哈希结果为 0,float('inf') 的哈希结果为 314159

参考资料:

https://docs.python.org/3/library/functions.html#float

https://www.pythondoeswhat.com/2019/09/welcome-to-float-zone.html

作者简介:

豌豆花下猫,生于广东毕业于武大,现为苏漂程序员,有一些极客思维,也有一些人文情怀,有一些温度,还有一些态度。

标签:

相关文章

phpfloat有误差技巧_PHP代码安然杂谈

一、精度绕过毛病理论在用PHP进行浮点数的运算中,常常会涌现一些和预期结果不一样的值,这是由于浮点数的精度有限。只管取决于系统,P...

PHP教程 2024-12-10 阅读0 评论0