甚至代码块的意外行为(mingw32g++)

evenUnexpected behaviour from Code Blocks (mingw32-g++ )

本文关键字:mingw32g++ 意外 代码      更新时间:2023-10-16

我正在写一些函数来转换整数的基数,我在Ideone上使用这个代码

虽然它在Ideone上工作得很好,但在C::B上它给出了输出484。我用的是-std=c++11,即使没有它(或使用-std=c++0x),输出仍然不正确。那么这是代码或编译器的问题吗?

我在windows上使用mingw (gcc 4.7.1)

#include<iostream>
#include<cmath>
#define bigint long long unsigned int
bigint base(int numberOldBase, int newBase)
{
    bigint numberNewBase = 0;
    int digitCounter = 0, remainder[100];
    while (numberOldBase)
    {
        remainder[digitCounter] = numberOldBase % newBase;
        numberOldBase /= newBase;
        digitCounter++;
    }
    for (int currentDigit = 0; currentDigit < digitCounter; currentDigit++)
    {
        numberNewBase += ((remainder[currentDigit]) * pow(10, currentDigit));
    }
    return numberNewBase;
}
int main()
{
    std::cout << base(1025, 15);
    return 0;
}

不准确的原因是浮点数不精确,如果在某些点上得到484.99999995,它在转换为int时被截断为484。在这种情况下,你应该把自己限制在整数算术,因为它会更快,并摆脱浮点数的不准确性。

bigint curExp = 1;
for (int currentDigit = 0; currentDigit < digitCounter; currentDigit++)
{
    numberNewBase += remainder[currentDigit] * curExp;
    curExp *= 10;
}

详细分析

 numberNewBase += ((remainder[currentDigit]) * pow(10, currentDigit));

被解释为

 numberNewBase = (float)numberNewBase + (((float)remainder[currentDigit]) * pow(10, currentDigit));

会导致大小浮点数相加的情况(这会导致更大的舍入误差)。

numberNewBase += (int)((remainder[currentDigit]) * pow(10.0, currentDigit));

方法通过在添加

之前将其转换为int来帮助缓解这个问题
numberNewBase = numberNewBase + (int)(((float)remainder[currentDigit]) * pow(10, currentDigit));

但是,使用top方法可以完全避免float转换