读书人

double 取整的精度有关问题

发布时间: 2012-06-08 12:55:24 作者: rapoo

double 取整的精度问题
对满二叉树进行按层次编号,
1,
2,3
4,5,6,7
8,9,10,11,12,13,14,15,
………………

输入为一个节点的值A,输出为节点所在层最左边的值B
A = 1, B = 1
A = 4或5或6或7 B = 4

想法是 先对A取2的对数, 然后取整后,再进行幂运算。

但是,当A = 8时,结果不正确,是由于 double转换成整形时,出现2 = (int)3.000000,不知道以后的数据还会不会出现这种情况,怎么解决呢?

C/C++ code
#include <stdio.h>#include <math.h>double logn(double n, double base){  return (log(n) / log(base));}int fun(int n){  double temp;  int stage;    temp = logn(n, 2);  stage = (int)temp;  return pow(2, stage);}void main(){  int i;    for (i = 1; i < 129; i++)  {    printf("%d, %d\n", i, fun(i));  }}

结果:
C/C++ code
1, 12, 23, 24, 45, 46, 47, 4[color=#FF0000]8, 4[/color]9, 810, 811, 812, 813, 814, 815, 816, 1617, 1618, 1619, 1620, 1621, 1622, 1623, 1624, 1625, 1626, 1627, 1628, 1629, 1630, 1631, 1632, 3233, 3234, 3235, 3236, 3237, 3238, 3239, 3240, 3241, 3242, 3243, 3244, 3245, 3246, 3247, 3248, 3249, 3250, 3251, 3252, 3253, 3254, 3255, 3256, 3257, 3258, 3259, 3260, 3261, 3262, 3263, 3264, 3265, 6466, 6467, 6468, 6469, 6470, 6471, 6472, 6473, 6474, 6475, 6476, 6477, 6478, 6479, 6480, 6481, 6482, 6483, 6484, 6485, 6486, 6487, 6488, 6489, 6490, 6491, 6492, 6493, 6494, 6495, 6496, 6497, 6498, 6499, 64100, 64101, 64102, 64103, 64104, 64105, 64106, 64107, 64108, 64109, 64110, 64111, 64112, 64113, 64114, 64115, 64116, 64117, 64118, 64119, 64120, 64121, 64122, 64123, 64124, 64125, 64126, 64127, 64128, 128


[解决办法]
double转到整形的话都是舍去小数位的,如果是2.99999999 也变成2。你这里的情况看似是3.0000,但可能你的double还不到3。所以转换的时候就变成了2。

其实你要做的是得到整数的log2(n)。通过移位就可以了,比自己做log要快
unsigned int log2(unsigned int n)
{
unsigned int result = 0;
while (n != 0) //不考虑n已经是0
{
result ++;
n >>= 1;
}
return result;
}

[解决办法]
C/C++ code
//Round(1.234,2) = 1.23//Round(1.234,0) = 1.0//Round(123.4,-1) = 120.0double Round(double dVal, short iPlaces) {    double dRetval;    double dMod = 0.0000001;    if (dVal<0.0) dMod=-0.0000001;    dRetval=dVal;    dRetval+=(5.0/pow(10.0,iPlaces+1.0));    dRetval*=pow(10.0,iPlaces);    dRetval=floor(dRetval+dMod);    dRetval/=pow(10.0,iPlaces);    return(dRetval);}double round(double dVal, short iPlaces) //iPlaces>=0{    unsigned char s[20];    double dRetval;    sprintf(s,"%.*lf",iPlaces,dVal);    sscanf(s,"%lf",&dRetval);    return (dRetval);} 

读书人网 >C语言

热点推荐