Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/107.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 浮动结果不准确_Ios_Objective C_Floating Point - Fatal编程技术网

Ios 浮动结果不准确

Ios 浮动结果不准确,ios,objective-c,floating-point,Ios,Objective C,Floating Point,可能重复: 你可能觉得这是一个基本的问题,但我花了两天的时间想弄清楚。 我搜索了一个解决方案,唯一的解释是float只使用4字节的内存。(那很有帮助……) 我有以下循环: double x = 0.0; for(int i = 0; i< 100; i++) { x = x + 0.01; NSLog(@"%f",x); } 但当我将double改为float时: 0.010000 0.02

可能重复:

你可能觉得这是一个基本的问题,但我花了两天的时间想弄清楚。 我搜索了一个解决方案,唯一的解释是float只使用4字节的内存。(那很有帮助……) 我有以下循环:

double x = 0.0;
        for(int i = 0; i< 100; i++)
        {
            x = x + 0.01;
            NSLog(@"%f",x);
        }
但当我将double改为float时:

0.010000
0.020000
0.030000
.
.
0.820000
0.830000
0.839999
0.849999
.
.
0.999999
正如你所看到的,计算机无法计算0.840000作为浮点数-_- 问题是我必须使用float,因为我使用的UIProgressView可以接受介于0.0到1.0之间的浮点数

如果我不能使用double,我能做什么?
谢谢。

使用
x=(i+1)*0.01而不是
x=x+0.01。它仍然不准确,因为
float
无法准确表示
0.84
,但至少错误不会累积。

使用
x=(i+1)*0.01而不是
x=x+0.01。它仍然不准确,因为
float
无法准确表示
0.84
,但至少错误不会累积。

如果您编写了以下代码:

int x = 0;
for(int i = 0; i< 100; i++)
{
    x = x + 3.5;
    NSLog(@"%d",x);
}
现在,您不仅将初始表示误差从舍入
0.1
累积到双倍,而且还将得到舍入误差,因为并非所有中间和都是可表示的。第二个错误源不出现在
int
示例中。计算的实际中间金额为:

0.01000000000000000020816681711721685132943093776702880859375
0.0200000000000000004163336342344337026588618755340576171875
0.0299999999999999988897769753748434595763683319091796875
0.040000000000000000832667268468867405317723751068115234375
0.05000000000000000277555756156289135105907917022705078125
0.060000000000000004718447854656915296800434589385986328125
...
0.990000000000000657252030578092671930789947509765625
1.0000000000000006661338147750939242541790008544921875
当您通过
%f
格式说明符将这些舍入到小数点后六位时,您会得到第三个舍入来源,但误差都很小,可以打印出您“期望”的结果

现在让我们看看当您使用
float
而不是
double
时会发生什么;由于C算术操作数提升规则,所有加法都在
double
中执行,但每次加法后,结果都被舍入回
float
,再次舍入。中间值的顺序如下所示:

0.00999999977648258209228515625
0.0199999995529651641845703125
0.02999999932944774627685546875
0.039999999105930328369140625
0.0500000007450580596923828125
0.060000002384185791015625
...
0.809999525547027587890625
0.819999516010284423828125
0.829999506473541259765625
到目前为止,误差很小,当四舍五入到六位小数时,它们仍然产生“预期”值。但是,计算的下一个值是

0.839999496936798095703125
因为这只比四舍五入到六位小数的精确中间情况小:

0.8399995
它向下舍入,打印的数字为:

0.8399999

现在,你能做些什么?当使用六位十进制数字打印时,错误最终会变得足够大,这是因为每次顺序加法都会累积错误。如果可以避免这种累积,错误将保持足够小,不会造成这种问题。有几种简单的方法可以避免这种累积误差;也许最简单的方法是:

for (int i=0; i<100; i++) {
    float x = (i+1)/100.f;
    NSLog(@"%d",x);
}

for(int i=0;i如果您编写了以下代码:

int x = 0;
for(int i = 0; i< 100; i++)
{
    x = x + 3.5;
    NSLog(@"%d",x);
}
现在,您不仅将初始表示误差从四舍五入
0.1
累加到两倍,而且还将得到四舍五入误差,因为并非所有中间和都是可表示的。第二个误差源不会出现在
int
示例中。实际计算的中间和为:

0.01000000000000000020816681711721685132943093776702880859375
0.0200000000000000004163336342344337026588618755340576171875
0.0299999999999999988897769753748434595763683319091796875
0.040000000000000000832667268468867405317723751068115234375
0.05000000000000000277555756156289135105907917022705078125
0.060000000000000004718447854656915296800434589385986328125
...
0.990000000000000657252030578092671930789947509765625
1.0000000000000006661338147750939242541790008544921875
当您通过
%f
格式说明符将这些舍入到小数点后六位时,您会得到第三个舍入来源,但误差都很小,可以打印出您“期望”的结果

现在让我们看看当您使用
float
而不是
double
时会发生什么情况;由于C算术操作数提升规则,加法都在
double
中执行,但每次加法后,结果都会取整回
float
,再次取整如下:

0.00999999977648258209228515625
0.0199999995529651641845703125
0.02999999932944774627685546875
0.039999999105930328369140625
0.0500000007450580596923828125
0.060000002384185791015625
...
0.809999525547027587890625
0.819999516010284423828125
0.829999506473541259765625
到目前为止,误差很小,当四舍五入到六位十进制数字时,它们仍然会产生“预期”值

0.839999496936798095703125
因为这只比四舍五入到六位小数的精确中间情况小:

0.8399995
它向下舍入,打印的数字为:

0.8399999

现在,你能做些什么呢?当用六位十进制数字打印时,错误最终变得足够大以至于出现的原因是,每次顺序加法都会累积错误。如果你能避免这种累积,错误将保持足够小而不会造成这种麻烦。有几种简单的方法可以避免这种情况累积错误;最简单的可能是:

for (int i=0; i<100; i++) {
    float x = (i+1)/100.f;
    NSLog(@"%d",x);
}

for(int i=0;谢谢你,现在比以前清楚多了!谢谢你,现在比以前清楚多了!