甚至来自代码块的意外行为(mingw32-g ++)

时间:2014-07-02 07:22:40

标签: c++ gcc codeblocks

我正在编写一些函数来转换整数的基数,我正在使用Ideone this code on 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;
}

1 个答案:

答案 0 :(得分:2)

不准确的原因是浮点数不准确,如果在某些时候得到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方法可以完全避免浮动转换。