一个有趣的有关问题?高手快来帮帮忙?
一个有趣的问题?高手快来帮帮忙???
下面是一个求一个数的小数位数和变成整数后的数的一个小程序,但是有一个问题,他可以算一些其他的数比如:95.123 1.0100 45.325 还有6.3421 7.5634 等等,但是不可以的到数 5.1234 , 6.1234 这样的数的结果 :这是为什么??高手帮帮忙:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <iostream>
using namespace std;
int main()
{
int i;
double n ;
while(cin > > n)
{
for( i = 1; ; i++)
{
n *= 10;
if(int(n) - n == 0)break;
}
cout < < "小数位数为: " < < i < < " " < < " 转换成整数为: " < < n < < endl;
}
system( "pause ");
return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
比如输入的是:95.123
输出的是:小数位数为:3 转换成整数为:95123
比如输入的是:1.0100
输出的是:小数位数为:2 转换成整数为:101
~~~~~~~~但是如果输入的是 5.1234 或是 6.1234 就不可以得到答案,请问这是为什么???
------解决方案--------------------
浮点型数据的比较不能用==
而应该使用一个比较小的数来判断。
改成如下就可以了
if(n - int(n) < 0.000001)break;//这就是认为这个数==0,因为浮点型本身是有精度的。
------解决方案--------------------
因为浮点数是有精度的,当无法精确达到一个数值时,浮点数取最接近的近似值。如5.1234存为double值时,实际上是5.1234000000000002(编译器VS2005)。此外浮点数做乘法时,仍然符合这个条件,如5.1234000000000002*10后,达到的近似值是51.234000000000002,但是再*10,近似值成为512.34000000000003。然后是5123.4000000000005,51234.000000000007,512340.00000000006,5123400.0000000009...。由于对浮点数而言,其精度是由定长的底数保证的,因此越大的数,偏差也越大。
kongz()提供的方法可以,需要改进一下的是n - int(n) 应取绝对值,因为偏差可正可负。
标准的做法是
#include <limits>
#include <cmath>
...
if( fabs(n - int(n))/n < numeric_limits <double> ::epsilon()) break;
其中fabs对浮点数求绝对值,fabs(n - int(n))/n 归一化(前提是n不为0,n==0的情况可另行判断),numeric_limits <double> ::epsilon()获得double的在1处的偏差。这样可以保证抵消浮点偏差。
下面是一个求一个数的小数位数和变成整数后的数的一个小程序,但是有一个问题,他可以算一些其他的数比如:95.123 1.0100 45.325 还有6.3421 7.5634 等等,但是不可以的到数 5.1234 , 6.1234 这样的数的结果 :这是为什么??高手帮帮忙:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <iostream>
using namespace std;
int main()
{
int i;
double n ;
while(cin > > n)
{
for( i = 1; ; i++)
{
n *= 10;
if(int(n) - n == 0)break;
}
cout < < "小数位数为: " < < i < < " " < < " 转换成整数为: " < < n < < endl;
}
system( "pause ");
return 0;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
比如输入的是:95.123
输出的是:小数位数为:3 转换成整数为:95123
比如输入的是:1.0100
输出的是:小数位数为:2 转换成整数为:101
~~~~~~~~但是如果输入的是 5.1234 或是 6.1234 就不可以得到答案,请问这是为什么???
------解决方案--------------------
浮点型数据的比较不能用==
而应该使用一个比较小的数来判断。
改成如下就可以了
if(n - int(n) < 0.000001)break;//这就是认为这个数==0,因为浮点型本身是有精度的。
------解决方案--------------------
因为浮点数是有精度的,当无法精确达到一个数值时,浮点数取最接近的近似值。如5.1234存为double值时,实际上是5.1234000000000002(编译器VS2005)。此外浮点数做乘法时,仍然符合这个条件,如5.1234000000000002*10后,达到的近似值是51.234000000000002,但是再*10,近似值成为512.34000000000003。然后是5123.4000000000005,51234.000000000007,512340.00000000006,5123400.0000000009...。由于对浮点数而言,其精度是由定长的底数保证的,因此越大的数,偏差也越大。
kongz()提供的方法可以,需要改进一下的是n - int(n) 应取绝对值,因为偏差可正可负。
标准的做法是
#include <limits>
#include <cmath>
...
if( fabs(n - int(n))/n < numeric_limits <double> ::epsilon()) break;
其中fabs对浮点数求绝对值,fabs(n - int(n))/n 归一化(前提是n不为0,n==0的情况可另行判断),numeric_limits <double> ::epsilon()获得double的在1处的偏差。这样可以保证抵消浮点偏差。