我正在做一些浮动操作并最终得到以下数字:
-0.5
-0.4
-0.3000000000000000004
-0.2000000000000000004
-0.1000000000000000003
1.10E-16
0.1
0.2
0.30000000000000000004
0.4
0.5
算法如下:
var inc:Number = nextMultiple(min, stepSize);
trace(String(inc));
private function nextMultiple(x:Number, y:Number) {
return Math.ceil(x/y)*y;
}
我理解浮点数不能总是在一个字节中准确表示。例如1/3。我也知道我的步数为0.1 。如果我有步骤,我怎么能得到一个合适的输出?
奇怪的是,这是我第一次遇到这类问题。 也许我玩不够漂浮。
答案 0 :(得分:8)
与语言无关的解决方案是将您的数字存储为整数步数,前提是您知道步长而不是浮点数。
非语言无关的解决方案是找出您的语言printf的实现方式。
printf ("float: %.1f\n", number);
答案 1 :(得分:3)
正如您所知,二进制数的有限浮点精度是您的问题。解决这个问题的一种方法是不进行浮点数学运算。将问题转换为整数,然后转换回输出。
答案 2 :(得分:1)
如果您使用的是具有圆形功能的语言,则可以使用该功能。
修改强>
在回复关于舍入的评论时,这是c#中的一个示例:
float value = 1.0F;
for (int i = 0; i < 20; i++)
{
value -= 0.1F;
Console.WriteLine(Math.Round(value, 1).ToString() + " : " + value.ToString());
}
结果是:
0.9:0.9
0.8:0.8
0.7:0.6999999
0.6:0.5999999
(等)
舍入确实解决了精度问题。我并不认为它比做整数数学然后除以10更好,只是它有效。
答案 3 :(得分:1)
使用整数而不是浮点类型,或使用浮点类型,其中“点”是小数点(例如.NET中的System.Decimal)。
答案 4 :(得分:0)
根据您的具体问题,在实际使用某事物的值之前,从-5到5计算并除以10。
答案 5 :(得分:0)
我做了以下,
var digitsNbr:Number = Math.abs(Math.ceil(((Math.log(stepSize) / Math.log(10))) + 1));
tickTxt.text = String(inc.toPrecision(digitsNbr));
效率不高但我没有太多步骤。
====== 我应该把步骤的nbr作为一个int并逐步加倍...
答案 6 :(得分:0)
如果你没有printf,或者步数不仅仅是10的幂(例如,如果你想要舍入到最近的0.2)那么听起来你想要一个量化器:
q(x,u)= u * floor(x / u + 0.5);
“u”是步长(在你的情况下为0.1),floor()找到不大于其输入的最大整数,“+ 0.5”将舍入到最接近的整数。
所以基本上,你除以步长,舍入到最接近的整数,然后乘以步长。
编辑:哦,没关系,你基本上都是这样做的&amp;它乘以u的步骤是引入舍入误差。
答案 7 :(得分:0)
简单地缩放数字以获得整数,然后进行数学运算并将它们缩放回浮点数进行显示:
//this will round to 3 decimal places var NUM_SCALE = 1000; function scaleUpNumber(n) { return (Math.floor(n * NUM_SCALE)); } function scaleDnNumber(n) { return (n / NUM_SCALE); } var answ = scaleUpNumber(2.1) - scaleUpNumber(3.001); alert(scaleDnNumber(answ)); // displays: -0.901
更改NUM_SCALE以增加/减少decimap位置
| / | AX
答案 8 :(得分:0)
这有点违反直觉,但我测试了它并且它有效(例如在AS3中):
var inc:Number = nextMultiple(min, stepSize);
trace(String(inc));
private function nextMultiple(x:Number, y:Number) {
return Math.ceil(x/y)*(y*10)/10;
}
所以我添加的唯一内容是将y
乘以10,然后除以10.不是通用解决方案,而是与stepSize一起使用。
[编辑:]这里的逻辑似乎是你乘以一个足够大的数字,以便最后的十进制数字“降低比例”,然后再次除以得到一个四舍五入的数字。也就是说,上面使用 Math.round()的示例更具可读性和更好,因为代码明确说明传入的数字会发生什么。
答案 9 :(得分:0)
如果您的语言支持,最好使用Decimal数据类型。为了解决这个问题,小数被添加到多种语言中。