在x64架构上运行,Visual Studio 2013 Windows 8.1
我正在尝试运行一个循环,它使用float作为循环变量,问题是在递增操作期间,十进制值丢失。
例如:
float incrementValue = 360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
我需要i&gt; = 360的值。但它停在350。 自360/14 = 25.7142857 但看起来增量是25步。 如果我对任何整数做同样的事情它工作正常,这个问题只有xx.yyyy的任何形式
我尝试在这个问题上查找各种网站,但我无法找到任何可以帮助我/回答我的问题。
答案 0 :(得分:3)
360 / 14
将为您提供整数结果。试试360.0 / 14.0
。
答案 1 :(得分:3)
这里有三个问题(两个相关),所有这些都可能有所帮助。
首先,浮点比较通常是不明智的,因为你可能认为你有360
,它实际上可能是359.999999942
。
第二,随着时间的推移,不准确性会逐渐增加。每当您添加{em>认为为0.99
的{{1}}这样的数字时,错误就会累积。
使用您正在使用的值,这些错误可能会保持很小但无论如何您都应该了解它们。如果您开始处理大量数字,您很快就会发现问题。
最终且无关的问题是1
是整数除法,它会给出整数结果360 / 14
而不是25
。
您可以通过确保其中一个值为浮点数来解决最终问题:
25.714285714
但那不会修复前两个,会在某些时候咬你。
要修复,你最好坚持使用整数(无论如何都是这个简单的情况)并在最新的可能实例中转换为浮点数:
float incrementValue = float(360) / 14;
给你:
#include<iostream>
int main (void) {
int incrementValue = 360;
for (int i = 0; i <= 360 * 14; i = i + incrementValue)
std::cout << " I " << float(i) / 14 << '\n';
return 0;
}
答案 2 :(得分:2)
很难得到'i = 360',因为'i = 360.0000001'将无法通过测试并且准确地获得'360'会很棘手。计算机上的浮点很难,而且很容易陷入困境。
最好尽可能使用整数: -
int num_steps = 14;
for (int i = 0 ; i <= num_steps ; ++i)
{
float value = 360.0f * i / num_steps;
// use value
}
在循环中使用'&lt; ='意味着你得到'值'为'360',因为'i / num_steps'是1。话虽如此,由于浮点错误,您可能无法得到'360.0f'。
答案 3 :(得分:1)
从分区浮点类型中生成操作数:
float incrementValue = 360.f / 14.f;
答案 4 :(得分:0)
float incrementValue = (float)360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
答案 5 :(得分:0)
如果你知道迭代次数,那么使用float来控制循环不是一个好主意,因为浮点数并不精确。
事实上,使用浮点控制任何循环是一个坏主意,不使用公差(这将取决于机械精度),以允许潜在的舍入误差。
在这种情况下,您知道迭代次数,因此像这样的循环可以解决问题。
int num_steps = 14
float factor = 360.0/num_steps;
for (int i = 0; i < num_steps; ++i)
{
std::cout << "\nI" << (i*factor);
}
答案 6 :(得分:0)
当我真的想在循环中使用浮点数时,我会更改上限以确保连续浮点错误没有错误。
float x_min = 0.;
float x_max = 360.;
int N_steps = 14;
float x_step = (x_max - x_min) / N_steps;
for (float x = x_min; x <= x_max + x_step / 2; x += x_step)
{
// do stuff
}
虽然这可以确保我每个步骤都正确,但如果有大量步骤,精度问题就会增加。在这种情况下,使用整数循环变量并每次计算相应的浮点数。然后我只有一次浮点错误而不是总计的14(或一百万)次。