使用 float / double 作为循环变量
Using float / double as a loop variable
运行 在 x64 架构上,Visual Studio 2013 Windows 8.1
我正在尝试 运行 一个使用浮点数作为其循环变量的循环,问题是在递增操作期间,十进制值正在丢失。
例如:
float incrementValue = 360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
我需要 i >= 360 的值。但它停在 350 。
由于 360/14 =25.7142857
但看起来增量是以 25 为步长的。
如果我对任何整数做同样的事情它都可以正常工作,这个问题只适用于 xx.yyyy
形式的任何数字
我尝试查找有关此问题的各种网站,但找不到任何可以帮助我/回答我问题的内容。
360 / 14
会给你一个整数结果。试试 360.0 / 14.0
.
你这里有三个问题(两个相关),所有这些问题都可能有贡献。
首先是浮点数比较通常是不明智的,因为虽然您可能 认为 您有 360
,但实际上可能是 359.999999942
。
第二个是随着时间的推移会出现不准确的情况。每次添加像 0.99
这样的数字时,您 认为 是 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;
}
这给你:
I 0
I 25.7143
I 51.4286
I 77.1429
I 102.857
I 128.571
I 154.286
I 180
I 205.714
I 231.429
I 257.143
I 282.857
I 308.571
I 334.286
I 360
将除法的操作数设为浮点型:
float incrementValue = 360.f / 14.f;
float incrementValue = (float)360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
很难获得 '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
}
在循环中使用“<=”确实意味着您得到 'value' 的“360”,因为 'i / num_steps' 是一个。话虽如此,由于浮点错误,您可能无法准确获得“360.0f”。
如果您知道迭代次数,那么使用浮点数来控制循环不是一个好主意,因为浮点数并不精确。
事实上,如果不使用公差(取决于机器精度)来考虑潜在的舍入误差,使用浮点数来控制任何循环都是一个坏主意。
在这种情况下,您知道迭代次数,因此像这样的循环就可以解决问题。
int num_steps = 14
float factor = 360.0/num_steps;
for (int i = 0; i < num_steps; ++i)
{
std::cout << "\nI" << (i*factor);
}
当我真的想在我的循环中使用浮点数时,我会更改上限以确保我不会因连续的浮点错误而出错。
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(或一百万)次。
运行 在 x64 架构上,Visual Studio 2013 Windows 8.1
我正在尝试 运行 一个使用浮点数作为其循环变量的循环,问题是在递增操作期间,十进制值正在丢失。
例如:
float incrementValue = 360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
我需要 i >= 360 的值。但它停在 350 。 由于 360/14 =25.7142857 但看起来增量是以 25 为步长的。 如果我对任何整数做同样的事情它都可以正常工作,这个问题只适用于 xx.yyyy
形式的任何数字我尝试查找有关此问题的各种网站,但找不到任何可以帮助我/回答我问题的内容。
360 / 14
会给你一个整数结果。试试 360.0 / 14.0
.
你这里有三个问题(两个相关),所有这些问题都可能有贡献。
首先是浮点数比较通常是不明智的,因为虽然您可能 认为 您有 360
,但实际上可能是 359.999999942
。
第二个是随着时间的推移会出现不准确的情况。每次添加像 0.99
这样的数字时,您 认为 是 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;
}
这给你:
I 0
I 25.7143
I 51.4286
I 77.1429
I 102.857
I 128.571
I 154.286
I 180
I 205.714
I 231.429
I 257.143
I 282.857
I 308.571
I 334.286
I 360
将除法的操作数设为浮点型:
float incrementValue = 360.f / 14.f;
float incrementValue = (float)360 / 14;
for (float i = 0; i <= 360; i = i + incrementValue)
{
cout << endl << " I " << i;
}
很难获得 '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
}
在循环中使用“<=”确实意味着您得到 'value' 的“360”,因为 'i / num_steps' 是一个。话虽如此,由于浮点错误,您可能无法准确获得“360.0f”。
如果您知道迭代次数,那么使用浮点数来控制循环不是一个好主意,因为浮点数并不精确。
事实上,如果不使用公差(取决于机器精度)来考虑潜在的舍入误差,使用浮点数来控制任何循环都是一个坏主意。
在这种情况下,您知道迭代次数,因此像这样的循环就可以解决问题。
int num_steps = 14
float factor = 360.0/num_steps;
for (int i = 0; i < num_steps; ++i)
{
std::cout << "\nI" << (i*factor);
}
当我真的想在我的循环中使用浮点数时,我会更改上限以确保我不会因连续的浮点错误而出错。
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(或一百万)次。