假设符合IEEE-754标准 ,是一个保证通过双重运输保留的浮法? 换句话说,下面的断言总会被满足吗? int main() { float f = some_random_float(); assert(f == (float)(double)f); } 假设f可以获得IEEE定义的任何特殊值,如NaN和Infinity。 根据IEEE的说法,是否有这样的情况,即assert会得到满足,但是在通过双重传输之后,确切的比特级表示不会被保留下来? 代码片段在C和C ++中都是有效的。
题 在Haskell中, base库和Hackage软件包提供了将二进制IEEE-754浮点数据转换为Float和Doubletypes浮点数据的多种方法。 但是,这些方法的准确性,性能和可移植性还不清楚。 对于旨在跨平台串行化二进制格式的GHC目标库,处理IEEE-754浮点数据的最佳方法是什么? 途径 这些是我在现有的库和在线资源中遇到的方法。 FFI封送 这是data-binary-ieee754软件包使用的方法。 由于Float , Double , Word32和Word64是Storable每个实例,因此可以将源types的值Word64外部缓冲区,然后peek目标types的值: toFloat :: (F.Storable word, F.Storable float) => word -> float toFloat word = F.unsafePerformIO $ F.alloca $ \buf -> do F.poke (F.castPtr buf) word F.peek buf 在我的机器上这工作,但我只看到分配执行,只是为了完成强制。 另外,虽然这个解决scheme并不是唯一的,但是这里有一个隐含的假设,即IEEE-754实际上是内存中的表示。 伴随包装的testing给了它“在我的机器上工作”认可的印章,但是这不是理想的。 unsafeCoerce 与内存中的IEEE-754表示相同的隐含假设,下面的代码也得到了“在我的机器上工作”的封印: toFloat :: Word32 -> Float toFloat = unsafeCoerce 这样做的好处是不像上面的方法那样进行明确的分配,但是文件中说“确保新旧types具有相同的内部表示是你的责任”。 这种隐含的假设仍然在做所有的工作,而且在处理被取消的types时更加费力。 […]
我可以知道Double.MIN_NORMAL (1.6中介绍)和Double.MIN_VALUE之间有什么区别吗? Double.MIN_NORMAL JavaDoc: 一个常量保持最小的正常值typesdouble ,2 -1022 Double.MIN_VALUE JavaDoc: 一个常量保持最小的正数非零值typesdouble ,2 -1074
我一直在阅读很多关于.NET中浮点确定性的知识,即确保具有相同input的相同代码将在不同的机器上得到相同的结果。 由于.NET缺乏诸如Java的fpstrict和MSVC的fp:strict之类的选项, 所以共识似乎是使用纯托pipe代码无法解决此问题。 C#游戏人工智能战争已经决定使用定点math ,但这是一个繁琐的解决scheme。 主要的问题似乎是CLR允许中间结果存在于FPU寄存器中,这些寄存器的精度比types本身的精度要高,从而导致精确的结果难以预测。 CLR工程师David Notario的MSDN文章解释如下: 请注意,在目前的规范下,它仍然是一个提供“可预测性”的语言select。 在每次FP操作之后,语言可以插入conv.r4或conv.r8指令以获得“可预测”的行为。 很明显,这个代价很高,不同的语言有不同的折中。 例如,C#不做任何事,如果你想缩小,你将不得不手动插入(浮动)和(双)转换。 这表明可以简单地通过为每个expression式和子expression式插入明确的强制转换来实现浮点确定。 有人可能会写一个浮动types的包装types来自动完成这个任务。 这将是一个简单而理想的解决scheme! 其他意见却表明这并不是那么简单。 Eric Lippert最近表示 (强调我的): 在运行时的某个版本中,明确地转换为浮动会产生比不这样做的结果。 当你明确强制转换为浮点运算时,C#编译器给运行时提示 “如果碰巧使用了这种优化,就把它从超高精度模式中拿出来”。 这是什么“提示”到运行时? C#规范是否规定明确的强制转换会导致在IL中插入conv.r4? CLR规范是否规定conv.r4指令将价值缩小到原始大小? 只有这两者都是真实的,我们才能依靠明确的演员来提供浮点“可预测性”,正如David Notario所解释的那样。 最后,即使我们确实可以将所有中间结果强制转换为原始大小,这足以保证机器之间的可重复性,还是还有其他因素,如FPU / SSE运行时设置?
我对IEEE-754浮点比较规则的理解是,除了!=之外的所有比较运算符将返回false,如果其中一个或两个参数都是NaN,而!=运算符将返回true。 我可以通过一个简单的独立testing轻松地重现此行为: for (int ii = 0; ii < 4; ++ii) { float a = (ii & 1) != 0 ? NAN : 1.0f; float b = (ii & 2) != 0 ? NAN : 2.0f; #define TEST(OP) printf("%4.1f %2s %4.1f => %s\n", a, #OP, b, a OP b ? "true" : "false"); TEST(<) TEST(>) […]
考虑下面的代码,这是我的实际问题的SSCCE : #include <iostream> int roundtrip(int x) { return int(float(x)); } int main() { int a = 2147483583; int b = 2147483584; std::cout << a << " -> " << roundtrip(a) << '\n'; std::cout << b << " -> " << roundtrip(b) << '\n'; } 我电脑上的输出(Xubuntu 12.04.3 LTS)是: 2147483583 -> 2147483520 2147483584 -> -2147483648 请注意,在往返之后,正数b如何结束的。 […]
我有这个例子,如何从一个基地10号码转换为IEEE 754浮点表示 Number: 45.25 (base 10) = 101101.01 (base 2) Sign: 0 Normalized form N = 1.0110101 * 2^5 Exponent esp = 5 E = 5 + 127 = 132 (base 10) = 10000100 (base 2) IEEE 754: 0 10000100 01101010000000000000000 除了一段话,这对我来说是有意义的: 45.25 (base 10) = 101101.01 (base 2) 45是101101在二进制,这没关系,但他们是如何获得0.25为0.01?
我最近在IEEE 754和x87架构上读了很多。 我正在考虑在我正在使用的一些数字计算代码中使用NaN作为“缺失值”,并且我希望使用NaN 信号发送将允许我在不希望出现的情况下捕获浮点exception着手“缺失的价值”。 相反,我会用安静的 NaN让“缺失值”通过计算传播。 然而,信号NaN不能正常工作,因为我认为它们是基于存在于其上的非常有限的文档。 这里是我所知道的一个总结(所有这些使用x87和VC ++): _EM_INVALID(IEEE“无效”exception)在遇到NaN时控制x87的行为 如果_EM_INVALID被屏蔽(exception被禁用),则不会产生exception,操作可以返回安静的NaN。 涉及NaN信号的操作不会引发exception,但会被转换为安静的NaN。 如果_EM_INVALID未被屏蔽(例外启用),一个无效的操作(例如,sqrt(-1))会导致一个无效的exception被抛出。 x87 永远不会产生信号NaN。 如果_EM_INVALID未被屏蔽, 任何使用信号NaN(甚至用它初始化一个variables)都会导致一个无效的exception被抛出。 标准库提供了一种访问NaN值的方法: std::numeric_limits<double>::signaling_NaN(); 和 std::numeric_limits<double>::quiet_NaN(); 问题是我看不到任何信号NaN。 如果_EM_INVALID被屏蔽,则其行为与安静的NaN完全相同。 由于没有NaN与任何其他NaN相比,没有逻辑差异。 如果_EM_INVALID 没有被屏蔽(exception被启用),那么甚至不能用信号发送一个variablesNaN: double dVal = std::numeric_limits<double>::signaling_NaN(); 因为这会引发一个exception(信号NaN值被加载到一个x87寄存器中以将其存储到存储器地址中)。 你可能会像我这样想: 掩码_EM_INVALID。 用信号NaN初始化variables。 Unmask_EM_INVALID。 但是,步骤2会导致信号NaN转换为安静的NaN,所以后续使用它不会引发exception! 那么WTF? 信号NaN有没有用处或目的? 我明白其中一个原意是用它初始化内存,以便可以捕获到单位浮点值的使用。 有人可以告诉我,如果我在这里失去了一些东西? 编辑: 为了进一步说明我希望做的事情,下面是一个例子: 考虑对数据向量执行math运算(双精度)。 对于某些操作,我想允许向量包含一个“缺失值”(假设这对应于一个电子表格列,例如,其中一些单元格没有值,但它们的存在是显着的)。 对于某些操作,我不想让vector包含“缺失值”。 也许我想采取一个不同的行动方式,如果一个“缺失的价值”是存在的设置 – 也许执行一个不同的操作(因此这不是一个无效的状态)。 这个原始代码看起来像这样: const double MISSING_VALUE = 1.3579246e123; using […]
我已经阅读了浮点数,并且我明白NaN可能来自操作。 但我完全不明白这些概念是什么。 有什么区别? 在C ++编程中可以生成哪一个? 作为一名程序员,我可以编写一个程序来创build一个sNaN吗?
我刚刚听说iPhone不能做双本机,从而使他们慢得多,正常的浮动。 这是真的? 证据? 我对这个问题非常感兴趣,因为我的程序需要高精度的计算,而且我将不得不在速度上妥协。