生成 n 个不是 ∞ 或 NaN 的不同浮点数(在 Go 中)
Posted
技术标签:
【中文标题】生成 n 个不是 ∞ 或 NaN 的不同浮点数(在 Go 中)【英文标题】:Generate n different floats that aren't ∞ or NaN (in Go) 【发布时间】:2016-11-11 01:01:27 【问题描述】:我想要一个函数getNthFloat(uint32 n) float32
,这样对于每个 n,m getNthFloat(n) 和 getNthFloat(m)
返回不同的浮点数,即实数(既不是 NaN 也不是 ±∞)。选择 2³²-4 是因为如果我正确理解 IEEE 754,NaN 有两种二进制表示,一种表示 ∞,一种表示 -∞。
我想我应该将我的 uint32 转换为位并将位转换为 float32,但我无法弄清楚如何有效地避免这四个值。
【问题讨论】:
【参考方案1】:您无法在 float32 中获得 2^32-4 个有效浮点数。 IEEE 754 binary32 数有两个无穷大(负数和正数)和 2^24-2 个可能的 NaN 值。
一个 32 位浮点数有以下几位:
31 30...23 22...0
sign exponent mantissa
所有值为 0xff 的指数要么是无穷大(当尾数为 0 时)或 NaN(当尾数不为 0 时)。所以你不能生成那些指数。
那么这只是一件简单的事情或将您允许的整数映射为这种格式,然后使用math.Float32frombits
生成一个float32。你怎么做是你的选择。我可能很懒惰,只使用最低位作为符号,然后拒绝所有高于 2^32 - 2^24 - 1 的数字,然后移动位。
所以像这样(未经测试):
func foo(n uint32) float32
if n >= 0xff000000
panic("xxx")
return math.Float32frombits((n & 1) << 31 | (n >> 1))
注意我可能还会避免非正规数,即指数为 0 且尾数非零的数字。它们可能很慢,并且可能无法正确处理。例如,它们都可以映射为零,go 规范中没有任何内容讨论如何处理非正规数,所以我会小心。
【讨论】:
哈,我没有意识到 NaN 有两个以上的二进制表示,但你是对的:play.golang.org/p/SIGEOULoFp 打印“nans: 16777213, infs: 2”。我测试了您的解决方案的改编版(以避免异常数字)并且它有效:play.golang.org/p/BPAyA0Ayo0。谢谢! @Ted:这很奇怪。应该是16777214
nans,而不是16777213
。 (即使不知道如何计算它们,NaN 也是成对出现的,因为翻转 NaN 的“符号位”会得到另一个 NaN。)
@Ted:啊,我明白了。在您链接到的第一个脚本中,您的 b < math.MaxUint32
应该是 b <= math.MaxUint32
。【参考方案2】:
我想你正在寻找math.Float32frombits
函数:https://golang.org/pkg/math/#Float32frombits
【讨论】:
嗯,是的,但是如果我只是在 n 的二进制表示上调用math.Float32frombits
,这会返回 NaN 或 ±∞,我该怎么办?以上是关于生成 n 个不是 ∞ 或 NaN 的不同浮点数(在 Go 中)的主要内容,如果未能解决你的问题,请参考以下文章
如何在包含浮点数和 Nan 或 None 值的同一列中舍入浮点值?