在不使用 modf() 的情况下获取浮点数的小数部分

新手上路,请多包涵

我正在开发一个没有数学库的平台,所以我需要构建自己的工具。我目前获取分数的方法是将浮点数转换为定点(乘以 (float)0xFFFF,强制转换为 int),仅获取下半部分(使用 0xFFFF 的掩码)并再次将其转换回浮点数。

然而,不精确正在杀死我。我正在使用我的 Frac() 和 InvFrac() 函数来绘制抗锯齿线。使用 modf 我得到一条非常平滑的线。使用我自己的方法,由于精度损失,像素开始跳跃。

这是我的代码:

 const float fp_amount = (float)(0xFFFF);
const float fp_amount_inv = 1.f / fp_amount;

inline float Frac(float a_X)
{
    return ((int)(a_X * fp_amount) & 0xFFFF) * fp_amount_inv;
}

inline float Frac(float a_X)
{
    return (0xFFFF - (int)(a_X * fp_amount) & 0xFFFF) * fp_amount_inv;
}

提前致谢!

原文由 knight666 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 840
2 个回答

如果我正确理解您的问题,您只需要小数点后的部分吗?您实际上不需要分数(整数分子和分母)?

所以我们有一些数字,比如 3.14159 并且我们希望只 0.14159 。假设我们的号码存储在 float f; 中,我们可以这样做:

 f = f-(long)f;

如果我们插入我们的号码,它的工作方式如下:

 0.14159 = 3.14159 - 3;

这样做是删除浮点数的整数部分,只留下小数部分。当您将浮点数转换为长整数时,它会删除小数部分。然后,当您从原始浮点数中减去它时,您 只剩 下小数部分。由于 float 类型的大小(大多数系统上为 8 字节),我们需要在这里使用 long。一个整数(在许多系统上只有 4 个字节)不一定大到足以覆盖与 float 相同的数字范围,但 long 应该是。

原文由 Daniel Bingham 发布,翻译遵循 CC BY-SA 3.0 许可协议

double frac(double val)
{
    return val - trunc(val);
}

// frac(1.0) = 1.0 - 1.0 = 0.0 correct
// frac(-1.0) = -1.0 - -1.0 = 0.0 correct
// frac(1.4) = 1.4 - 1.0 = 0.4 correct
// frac(-1.4) = -1.4 - -1.0 = -0.4 correct

简单,适用于 -ve 和 +ve

原文由 TheWhitde 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题