如何检测基数10十进制是否可以在基数2中精确表示

Sam*_*mil 2 c++

作为数值库测试的一部分,我需要选择可以在基数2中精确表示的10位十进制数.如何在C++中检测基数为10的十进制数是否可以在基数2中精确表示?

我的第一个猜测如下:

bool canBeRepresentedInBase2(const double &pNumberInBase10)
{
    //check if a number in base 10 can be represented exactly in base 2
    //reference: http://en.wikipedia.org/wiki/Binary_numeral_system
    bool funcResult = false;

    int nbOfDoublings = 16*3;
    double doubledNumber = pNumberInBase10;
    for (int i = 0; i < nbOfDoublings ; i++)
    {
        doubledNumber = 2*doubledNumber;
        double intPart;
        double fracPart = modf(doubledNumber/2, &intPart);
        if (fracPart == 0) //number can be represented exactly in base 2
        {
            funcResult = true;
            break;
        }
    }
    return funcResult;
}
Run Code Online (Sandbox Code Playgroud)

我用以下值测试了这个函数:-1.0/4.0,0.0,0.1,0.2,0.205,1.0/3.0,7.0/8.0,1.0,256.0/255.0,1.02,99.005.对于-1.0/4.0,0.0,7.0/8.0,1.0,99.005,它返回true,这是正确的.

有更好的想法吗?

Eva*_*ran 5

我认为你所寻找的是一个数字,它有一个小数部分,它是一系列2的负幂(也就是:2的2次幂)的总和.我相信这应该始终能够在IEEE浮点数/双打中完全表示.

例如:

0.375 =(1/4 + 1/8)应具有精确的表示.

如果你想生成这些.你可以尝试做这样的事情:

#include <iostream>
#include <cstdlib>

int main() {
    srand(time(0));
    double value = 0.0;
    for(int i = 1; i < 256; i *= 2) {
        // doesn't matter, some random probability of including this
        // fraction in our sequence..
        if((rand() % 3) == 0) {
            value += (1.0 / static_cast<double>(i));        
        }
    }
    std::cout << value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

编辑:我相信你的功能有一个破碎的界面.如果你有这个会更好:

bool canBeRepresentedExactly(int numerator, int denominator);
Run Code Online (Sandbox Code Playgroud)

因为并非所有分数都具有精确的表示形式,但是当你把它推到一个双精度表中时,你已经选择了二进制表示法......从而破坏了测试的目的.