如何将模数用于浮点/双精度?

Posted

技术标签:

【中文标题】如何将模数用于浮点/双精度?【英文标题】:How do I use modulus for float/double? 【发布时间】:2011-02-26 04:25:32 【问题描述】:

我正在为一个学校项目创建一个 RPN 计算器,但在使用模数运算符时遇到了问题。由于我们使用的是双精度数据类型,因此模数不适用于浮点数。例如,0.5 % 0.3 应该返回 0.2,但我得到了除以零的异常。

指令说使用fmod()。我到处寻找fmod(),包括javadoc,但我找不到。我开始认为这是我必须创建的一种方法?

编辑:嗯,奇怪。我刚刚再次插入这些数字,它似乎工作正常……但以防万一。在使用浮点类型时,我是否需要注意在 Java 中使用 mod 运算符?我知道这样的事情不能在 C++ 中完成(我认为)。

【问题讨论】:

【参考方案1】:

我认为常规模数运算符在 Java 中可以解决这个问题,但编写代码并不难。只需将分子除以分母,然后取结果的整数部分。将其乘以分母,然后从分子中减去结果。

x = n/d
xint = Integer portion of x
result = n - d*xint

【讨论】:

在逻辑上有意义,但不适用于实际实现 @Valen:更具体地说,它是四舍五入,而大多数真正的余数运算(包括 Java 的 %IEEEremainder)都是精确的。【参考方案2】:

您第一次运行它时可能有错字。

评估 0.5 % 0.3 会按预期返回“0.2”(双精度)。

Mindprod 在 Java 中有一个 good overview of how modulus works。

【讨论】:

但由于舍入错误,1.0 % 0.1 返回 ...0.09999999999999995。知道如何纠正这个问题(大概使用 epsilon 值?) 在浮点计算中总是会发生舍入错误。要么取给定的值,要么将其四舍五入到最接近的必要值。 String.format("%.8f",1.0%0.1) 返回0.10000000 @Groostav 这不是舍入错误。 0.1 不能表示为双精度值,因此结果是最接近的可表示双精度值。 这比四舍五入的结果更糟糕。你说的是1.0 % 0.1,但你实际做的是1.0 % 0.10000000000000000555111512...,所以如果你增加1.0,答案会越来越远离0.1。【参考方案3】:

fmod 是处理浮点模数的标准 C 函数;我想您的消息来源是说 Java 处理浮点模数与 C 的 fmod 函数相同。在 Java 中,您可以对双精度数使用 % 运算符,就像对整数一样:

int x = 5 % 3; // x = 2
double y = .5 % .3; // y = .2

【讨论】:

【参考方案4】:

与 C 不同,Java 允许将 % 用于整数和浮点数,并且(与 C89 和 C++ 不同)它对所有输入(包括负数)都有很好的定义:

来自JLS §15.17.3:

浮点数的结果 余数运算由下式确定 IEEE算术规则:

如果任一操作数为 NaN,则结果为 NaN。 如果结果不是 NaN,则结果的符号等于 分红。 如果被除数为无穷大,或除数为零,或两者兼有,则 结果是 NaN。 如果被除数是有限的且除数是无穷大,则结果 等于股息。 如果被除数为零且除数是有限的,则结果 等于股息。 在其余情况下,既不是无穷大,也不是零,也不是 涉及到 NaN,浮点数 a 的除法余数 r 除数 n 被除数 d 定义 由数学关系 r=n-(d·q) 其中 q 是一个负整数 仅当 n/d 为负数和正数时 仅当 n/d 为正时,并且其 幅度尽可能大 在不超过幅度的情况下 n 和 d 的真正数学商。

因此,对于您的示例,0.5/0.3 = 1.6...。 q与0.5(被除数)同号(正),大小为1(最大大小不超过1.6大小的整数...),r = 0.5 - (0.3 * 1) = 0.2

【讨论】:

最后一个要点是一堵文字墙。举个例子会更清楚:0.5 % 0.3 = 0.2(-0.5) % 0.3 = -0.2

以上是关于如何将模数用于浮点/双精度?的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中将十进制/双精度/浮点值与 PDO 绑定的最佳方法是啥?

如何保持浮点/双精度算术确定性?

如何在 PySpark 1.6 中将 DataFrame 列从字符串转换为浮点/双精度?

精度浮点型数据精确到了几位小数呢?

解决浮点型数值计算精度丢失的一种实现

如何在Java中将浮点数组转换为双精度数组?