gpt4 book ai didi

android - 定点数学 - 从浮点安全到总是产生相同结果的转换?

转载 作者:可可西里 更新时间:2023-11-01 05:51:17 24 4
gpt4 key购买 nike

我正在使用 libfixmath 进行模拟,需要同时在两个设备(iOS/Android)上进行并且非常准确。

模拟需要输入一些初始 float 参数。我想知道,使用 float 然后按照下面的方式将它们转换为 fix16_t 是否安全(该函数来自库),或者我是否需要已经为模拟提供 fix16_t 值?

因此,是否有可能由于浮点不准确,两个不同的设备使用相同的输入为下面的函数计算出不同的结果?

typedef int32_t fix16_t;
static const fix16_t fix16_one = 0x00010000; /*!< fix16_t value of 1 */

static inline fix16_t fix16_from_float(float a)
{
float temp = a * fix16_one;

// rounding
temp += (temp >= 0) ? 0.5f : -0.5f;
return (fix16_t)temp;
}

最佳答案

假设:

  • 两台机器都使用 IEEE-754 单精度浮点表示法表示 float,并且

  • a是“合理的”

转换应该是可移植的,a 的绝对值略小于 0.5×2−16 的情况可能是异常(exception)。

将(二进制) float 乘以 2 的幂(在本例中为 216)是精确的,前提是它不会导致浮点溢出(或下溢,在这种情况下) 2) 的负幂。每个浮点实现都应该以完全相同的方式处理乘法。

C++ 标准要求从 float 到整数类型的转换才能截断到 0,因此舍入策略是正确的。

将 0.5 添加到 temp 几乎在所有情况下都会产生正确的结果。

对于 temp 的中间值,结果将是精确的。

如果 temp 大于 223,加法将没有效果,但没有小数要四舍五入,所以只要最终结果是可预测的因为在转换回整数时没有溢出。

如果 temp 小于 1.0,则总和将不精确,因为指数会增加。然后加法应该舍入以产生正确的结果。在这里,唯一感兴趣的情况是截断和可能为 0 或 1;如果 temp 不接近 0.5,则总和不能为 1.0,截断的总和必须为 0。如果 temp 至少为 0.5,则总和必须至少为 1.0,截断和必须为 1。

但如果 temp 略小于 0.5,则总和的四舍五入可能很重要。特别是,如果 temp 恰好为 0.5−2−25,则存在歧义。总和的结果将为 1.0−2−25,但该值不能精确表示为 IEEE-754 单精度 float 。此外,误差项恰好是 ULP 的二分之一。所以结果需要四舍五入,这将服从实现的四舍五入模式。

IEEE-754 的默认舍入模式是 "banker's rounding" ,其中恰好二分之一的值四舍五入是针对两种可能性中的任何一种,其低位为 0。这将有利于将 0.5−2−25 + 0.5 舍入到 1.0,这将产生不正确的整数截断 1。但是,给定的实现可能使用不同的舍入模式,也许是因为它已经使用 std::fesetround 设置.

以上所有内容同样适用于负值。

关于android - 定点数学 - 从浮点安全到总是产生相同结果的转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34769921/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com