以下是一组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,它在某一点上很难解释.我仍然很高兴我写了这篇文章,因为我相信这是很好的信息,而且很有趣.)