java-什么是一种与Math.floorMod()完全一样的方法,但使用浮点数而不是整数?

以下是一组Math.floorMod(x, 5)的输入和输出作为示例.

int x;

inputs:
x = -15 | -14 | -13 | -12 | -11
    -10 | -09 | -08 | -07 | -06
    -05 | -04 | -03 | -02 | -01
    +00 | +01 | +02 | +03 | +04*
    +05 | +06 | +07 | +08 | +09
    +10 | +11 | +12 | +13 | +14

outputs:
   *+00 | +01 | +02 | +03 | +04

请注意,第1列中的所有输入都会导致第1列中的输出,依此类推.

我也希望能够使用float来执行此操作,但是我一直找不到任何Math.relevantMethod()来帮助我.这个想法是,所有浮点数都应映射到Pac-Man样式介于0和y(第二个参数)之间的浮点数范围内.

解决方法:

我花了一些时间来开发算法并解决所有问题,但事情就在这里.我将其复制为floatMod().

double floatMod(double x, double y){
    // x mod y behaving the same way as Math.floorMod but with doubles
    return (x - Math.floor(x/y) * y);
}

这是floatMod(x,2.0d)的一组输入和输出作为示例. (我修复了轻微的舍入错误,只是为了使表整洁.)

double x;

inputs:
x = -4.0 | -3.6 | -3.2 | -2.8 | -2.4
    -2.0 | -1.6 | -1.2 | -0.8 | -0.4
    +0.0 | +0.4 | +0.8 | +1.2 | +1.6*
    +2.0 | +2.4 | +2.8 | +3.2 | +3.6
    +4.0 | +4.4 | +4.8 | +5.2 | +5.6

outputs:
   *+0.0 | +0.4 | +0.8 | +1.2 | +1.6

提示:为减少舍入错误,请确保在floatMod()中输入了double.输入文字0.8等效于输入精度不如0.8d的(double)0.8f.即使将输出强制转换为浮点数,也将获得更精确的结果.还要注意,距离0.0 x越远,舍入误差越大.这就是浮动的工作方式.所以…

floatMod(0.1f, 1f);     //returns: 0.1
floatMod(1.1f, 1f);     //returns: 0.100000024 aka 0.1 + 0.000000024
floatMod(2.1f, 1f);     //returns: 0.099999905 aka 0.1 - 0.000000095
floatMod(10000.1f, 1f); //returns: 0.099609375 aka 0.1 - 0.000390625

floatMod(0.1d, 1d);     //returns: 0.1
floatMod(1.1d, 1d);     //returns: 0.10000000000000009 aka 0.1 + 0.00000000000000009
floatMod(2.1d, 1d);     //returns: 0.10000000000000009 aka 0.1 + 0.00000000000000009
floatMod(10000.1d, 1d); //returns: 0.10000000000036380 aka 0.1 - 0.00000000000036380

算法说明

如果您对算法x-Math.floor(x / y)* y的工作方式感兴趣,我将尽力解释.让我们使用上面的floatMod(x,2.0d)示例.

首先,对x取以下可能的数值行:

                                ●------------------------○
       |                        |                        |                        |
-2.4 -2.0 -1.6 -1.2 -0.8 -0.4 +0.0 +0.4 +0.8 +1.2 +1.6 +2.0 +2.4 +2.8 +3.2 +3.6 +4.0 +4.4

垂直线之间的间隔表示在两个方向上并排堆叠的长度为y的块.实心圆表示包含,而空心圆表示排除,并且上面所示的那些包含虚线表示的块0.

接下来,x / y(在这种情况下为y = 2.0)在数字行x上占据一个给定位置,并给出其块数.因此,2.0是块0的末尾和块1的开始,所以2.0 / y = 1.0.

我们说x / y = c;

1.0 / y→0.5c,因为1.0是一半
3.2 / y→1.6c
-2.4 / y→-1.2c
等等

接下来,Math.floor(c)表示我们在哪个块中,将c减小到所述块的开头.换句话说,x在哪个位置?

0.5c→0.0c
1.6c→1.0c
-1.2c→-2.0c

接下来,它将结果再次乘以y,以x取回.

0.0c * y→0.0
1.0c * y→2.0
-2.0c * y→-4.0

最后,它只是获取此值并计算x与它的距离,如x与它所在的块的开头有多远?

另一种看待它的方法:它需要减去x中多余的数据块,因此它计算出0数据块中正向或反向x数据块的数量,并删除该数量.这使它保持在0和y的范围内.

1.0-0.0→1.0
3.2-2.0→1.2
-2.4–4.0→1.6

(嗯……好吧,在写完大部分算法解释后,我意识到有一种方法可以简化它.我做了之后,我意识到它实际上与floorMod算法完全相同,只是有浮点数.我“我在这里的行为就像某种聪明的人,当我所做的一切都比我的鼻子下面要走出一步时,他发现了所有事物的统一理论.我保证我会尽全力从头开始发展这一点.

我最初使用的算法是-Math.floor(x / y)* y x,它在某一点上很难解释.我仍然很高兴我写了这篇文章,因为我相信这是很好的信息,而且很有趣.)

上一篇:B. Modulo Equality


下一篇:为什么不能在if语句中直接使用取模运算的结果?