在C++中,有些数字消失了,你永远不可能找到它们、显示它们或者计算它们。因为它们消失了!它们不可能在C++中被表示出来,不相信吗?

  请试试下面的代码吧:

      double a = 0.2;

  在它后面设个断点然后运行它,查看一下它的值。是什么?会是0.2吗?不的,在我的电脑上,它是0.20000000000000001。在其他的电脑上它可能是0.20000000000000002或者0.19999999999999998,但是它永远不可能是0.2。不管你用什么电脑,或者什么编译器。

  原因挺简单的,你可以在计算机组成原理的课程中找到它,这还是一门很重要的专业课。但是大部分程序员在他们知道这一点的时候就忘记了这一点。原因是因为计算机使用二进制而我们使用十进制,而且计算机是有限的。

  我们都知道,有些分数是有限小数,比如三分之五,它是0.6;但是有些不是,它们是无限不循环小数,比如三分之一,它是0.333……,这些在我们小学生的时候就很熟悉了。但是这些仅仅是我们更加熟悉的十进制世界下的情况。在其他的进制系统下原来的无限循环小数可能会变成有限小数,但是原来的有限小数却可能变成无限不循环小数。比如,在三进制下面,三分之一就是0.1,而不是0.333……。当然,这是个无限循环小数变成有限小数的例子,那么有限小数变成无限循环小数的例子是……

  猜对了,正是0.2到了二进制下就成了无限循环小数。

  由于另外一个原因,计算机是有限的,所以它不能精确表述无限的东西,C++也是一样。所以在你写程序的时候如果遇到浮点数,一定多小心啊!今天我的一个同事就遇到了这样的问题,折腾了一下午。这也是我想到写这篇文章的原因。

  我写了个程序来演示原因,但是还没调试它,试试吧,有bug请留言。它的目的是把个(0,1)区间的小数(这个叫纯小数吧),分解成用二的幂来表示的形式。你需要用Visual C++ 2003来编译它,因为我用了微软保留关键字__int64。然后在运行的时候,先输入分子,然后输入分母,按回车。

#include <iostream>

int BinPower(unsigned __int64& m, unsigned __int64& n, unsigned __int64& binSum, int power);
int main()
{
unsigned __int64 m, n, binSum;
int p;
std::cin >> m >> n;//input m, n

binSum = 1;
p = 0;
std::cout << m << "/" << n << " = ";
while(m < n && m != 0)
{
    p = BinPower(m, n, binSum, p);
    std::cout << "+ 2 ^" << p << " ";
}
std::cout << "\n";
}
int BinPower(unsigned __int64& m, unsigned __int64& n, unsigned __int64& binSum, int power)
{
if (m < n)
{
    while(binSum * m < n)
    {
     binSum *= 2;
     --power;
    }
    m = binSum * m - n;
    n = binSum * n;
    unsigned __int64 r1 = m, m1 = m, n1 = n;
    while(r1 != 0)
    {
     r1 = n1 % m1;
     n1 = m1; 
     m1 = r1;
    }
    m = m / n1;
    n = n / n1;
    return power;
}
else
    return 1;
}

[原文在百度空间已经关闭]