如何将模数用于浮点/双精度?
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 绑定的最佳方法是啥?