生成 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:这很奇怪。应该是16777214nans,而不是16777213。 (即使不知道如何计算它们,NaN 也是成对出现的,因为翻转 NaN 的“符号位”会得到另一个 NaN。) @Ted:啊,我明白了。在您链接到的第一个脚本中,您的 b &lt; math.MaxUint32 应该是 b &lt;= math.MaxUint32【参考方案2】:

我想你正在寻找math.Float32frombits函数:https://golang.org/pkg/math/#Float32frombits

【讨论】:

嗯,是的,但是如果我只是在 n 的二进制表示上调用 math.Float32frombits,这会返回 NaN 或 ±∞,我该怎么办?

以上是关于生成 n 个不是 ∞ 或 NaN 的不同浮点数(在 Go 中)的主要内容,如果未能解决你的问题,请参考以下文章

如何在 c 中产生 NaN 浮点数?

关于IEEE754标准浮点数阶码的移码

如何在包含浮点数和 Nan 或 None 值的同一列中舍入浮点值?

将 NAN 浮点数转换为 int 的问题

浮点数或双精度数的 NaN 和 Infinity 如何存储在内存中?

写入期望类型不是浮点数的数据库时如何处理 NaN 值?