使用十进制值递增for循环

increment of a for loop with a decimal value

本文关键字:for 循环 十进制      更新时间:2023-10-16

首先让我说我已经检查了相关主题问题是,我想创建一个步长为十进制的for循环我已经准备了下面的代码来解决这个问题,但它没有生成准确的数字与上述步长

 float b;

   for ( double a=-0.2; a<=0.2 ; a+=0.01)// a = landa with an increment of 0.1
    {
        b = a * 100.0;
    a = ((int)b) / 100.0;
}

我想要的是在每次迭代中有一个准确的数字,但作为变量定义为双精度,这只是接近它必须的值(-0.20000000001,-0.19000000002,....)。请告诉我如何解决这个问题。代码有什么问题?

而不是:

for (double a = -0.2; a <= 0.2; a += 0.01)
{
    ...
}

使用整数循环索引并在循环中计算相应的浮点值,例如

for (int i = -20; i <= 20 ; ++i) // a = -0.2 to 0.2 step 0.01
{
    const double a = i / 100.0;
    ...
}

要进行精确小数的计算,您可以使用像bdldfp::Decimal64这样的十进制浮点类:十进制浮点不使用计算机擅长计算的基数2,而是使用基数10。因此,它们的处理速度较慢(目前使用IBM的decNumber的实现确实不是很好,但它正在使用英特尔的实现进行纠正)。在返回值中,十进制计算是精确的:

using namespace BloombergLP;
bdldfp::Decimal64 a(BDLDFP_DECIMAL64_DD(-0.2));
bdldfp::Decimal64 add(BDLDFP_DECIMAL64_DD(0.01));
bdldfp::Decimal64 end(BDLDFP_DECIMAL64_DD(0.2));
for (; a <= end; a += add) {
    std::cout << a << 'n';
}

使用c++ 11的特性(例如,使用_DD作为字面值后缀)可以使实现看起来更好,但它也意味着在c++ 03编译器上运行。我正在努力将十进制浮点类添加到c++标准中(这是该提案的最新版本)。

当使用二进制浮点数时,例如,double,您将无法准确地表示这些值。您可能会根据整数进行迭代并在每次迭代中进行适当的除法,从而得到最接近的值:

for (int a(-20); a <= 20; ++a) {
    std::cout << (a / 100.0) << 'n';
}

当直接使用double,每次迭代加入0.01时,会产生一些舍入误差,增加了前一个值的不准确性。

使用以下语句:

double min = -0.2;
double max = +0.2;
int N = 40;
for(int i=0; i<=N; i++) {
    double a = min + static_cast<double>(i)*((max - min)/static_cast<double>(N));
    double b = a * 100.0;
    ...
}

这个语句也是一个潜在的问题:

    a = ((int)b) / 100.;

因为(int)b将截断b趋向0。例如,如果b == 101.9999999999,那么(int) b将产生101(而不是102)。为了保持最初的概念,尝试这样做:

double a;
int b;
    for(a = -.2; a <= .2; a += .01){
        b = (int)(a*100. + ((a < -0.005)? -.5 : .5));
        a = (double)b / 100.;
    }

注,(a <- 0.005)是对负a的检查,误差范围为步进率的1/2。

仍然像其他人发布的那样,使用整数进行循环并根据整数设置'a'将是更好的解决方案。