我最近做了一道题,一个64位(unsigned __int64)范围内的数输出其除以1000的值,并按四舍五入保留小数点后三位。

我刚开始直接写WA,结果发现当数比较大的时候,结果后几位精度总会丢失,只好手动模拟了一个,水过。。。。

后来我在网上找到了某位大牛的博客,这篇文章让我对数据类型有了更好的认识。。

谢谢,转载自http://blog.csdn.net/cai870808/article/details/24907853

看了一篇关于C/C++浮点数的博文,在Win32下,把int, 指针地址,long等4字节整数赋给一个double后,再用该double数赋给原始类型的数,得到的结果于最初的数值一致,即不存在任何精度丢失。例如下面的结果将总是true:

long a=123456; //assign any long number here

double db=a;long b=db;

printf("%s\n",a==b?"true":"false");

但是对于long long或win64下的指针地址等8字节整数将存在精度丢失,于是对这方面做了一个简单的测试:

#include#include

void showEncodeOfDouble(unsigned char*db){const int ByteLength=8;for(int i=ByteLength-1;i>=0;i--)

printf("%.2x",db[i]);

printf("\n");

}intmain(){

unsignedlong long maxULL=0xffffffffffffffff; //2^64-1=18446744073709551615,//max unsigned long long

printf("%llu\n",maxULL);double d1=maxULL; //20bit Significant,Precision Loss

printf("%f\n",d1);

maxULL=d1;

printf("%llu\n",maxULL);

showEncodeOfDouble((unsignedchar*)&d1);

system("pause");return 0;

}

输出的结果如下(visual studio,win32):

18446744073709551615

18446744073709552000.000000

9223372036854775808

43 f0 00 00 00 00 00 00

至此,有两点疑问(暂时不理会代码中showEncodeOfDouble的结果):

1)为什么丢失精度后得到的double数是18446744073709552000.000000?

2)为什么将double数重新转化为unsigned long long后得到的数又和double不一致呢?对于这两个问题,需要对C++浮点数的规格有一定的了解。

1  IEEE浮点标准

C/C++采用的是IEEE浮点标准,它以“二进制的科学表示法”表示一个小数:

其中M是一个整数部分仅有一位的二进制小数,例如1.011,表示十进制下的1.375。E表示该小数以2为底时的阶数。基于以上的表示方式,小数需要对三部分进行编码:表示符号的s,及阶码E、尾数码M。C++中的double类型三种编码所占的位数如图所示。

53位尾数码所能达到的精度为53二进制位,约为16 个十进制位( 53 log10(2) ≈ 15.955)[1],尾数码的编码中还有一个隐含的开头整数位1(或0,当11位阶码全0时)因此实际中可得15-17位十进制的精度。当有效位数最多15位的十进制数转换成double然后重新转换为原来的十进制类型时,数值保持一致;另一方面,将一个double数转化为可以容纳17位以上有效数字的十进制数再重新转化为double,结果数值也保持一致。

这就解释了为什么4字节的整数转化为double重新转化能保持一致(2^32=4294967296仅10个有效位),而8字节的整数却可能丢失精度(2^64-1=18446744073709551615共20个有效位)。但第一个问题中整数丢失精度后转化成的double数值是怎么来的呢,这需要了解C++阶码和尾数对于double数值的意义。

2 阶码编码和尾数编码

在阶码编码中,有一个常数偏置量Bias=1023,假设11位阶码所代表的无符号整数值为e,

1)若e不为0(11位全为1时用于表示特殊数字,此处不讨论),则double数值为

2)若e=0,则小数值为

那么,可以看函数showEncodeOfDouble了,它的作用是将一个double数的编码按字节打印出来(左边是高字节),按其打印结果按照上面计算,可知double编码值表示的数值是2^64,这是合理的,当把精度较高的整数转化为double时,C++采用向偶数舍入的方式得到最接近的值[2]。至于打印出的结果,属于C++浮点数打印中的细节问题。

3 C++浮点数打印

许多C/C++的库中在输出double时,通常有意使得输出结果简短些(即使设置了足够多的可见位数),以避免较大位数的输出。直接使用C中的printf或cout打印double数时,打印显示的结果也有可能是带有精度丢失的结果,可使用16进制的方式打印出更精确的double:

printf("%a\n",d1);

得到的输出结果为:

0x1.000000p+64

至此问题1实际上只是C++中,将高精度整数转double时的偶数舍入问题。

对于问题2,从float或double转换成int,值将会被向零舍入.例如1.999将被转换成1而-1.999将会被转换成-1。进一步来说,值有可能会溢出。C语言标准没有对这种情况指出固定的结果,这种转换行为是无定义的。

[2]深入理解计算机系统,Randal E. Bryant, 机械工业出版社

java long double精度丢失_long long类型转double类型部分精度丢失问题相关推荐

  1. Java中double类型精度丢失的问题_double类型数据加减操作精度丢失解决方法_BigDecimal取整

    BigDecimal在用double做入参的时候,二进制无法精确地表示十进制小数,编译器读到字符串"0.0000002"和"1.0000002"之后,必须把它转 ...

  2. 怎么设置java的精度值_Java:如何为double值设置Precision?

    本问题已经有最佳答案,请猛点这里访问. 我最近正在处理数字,我有一种情况,我想将双精度值的精度设置为6位或4位,这取决于数据库中存储的值. 例如,如果在数据库中,精度设置为4位,则输出必须如下所示: ...

  3. Long类型转json时前端js丢失精度解决方案

    Long类型转json时前端js丢失精度解决方案 参考文章: (1)Long类型转json时前端js丢失精度解决方案 (2)https://www.cnblogs.com/lvgg/p/7475140 ...

  4. JAVA实体类不要使用基本类型,基本类型包含byte、int、short、long、float、double、char、boolean...

    由于JAVA的基本类型会有默认值,例如当某个类中存在private  int age;字段时,创建这个类时,age会有默认值0.当使用age属性时,它总会有值.因此在某些情况下,便无法实现age为nu ...

  5. 浮点数精度问题透析:小数计算不准确+浮点数精度丢失根源

    在知乎上上看到如下问题: 浮点数精度问题的前世今生? 1.该问题出现的原因 ? 2.为何其他编程语言,比如java中可能没有js那么明显 3.大家在项目中踩过浮点数精度的坑? 4.最后采用哪些方案规避 ...

  6. python 浮点数精度丢失_浮点数精度问题透析:小数计算不准确+浮点数精度丢失根源...

    浮点数精度问题透析:小数计算不准确+浮点数精度丢失根源 无论在java python javaScript里面都存在 1+ 2!== 3 问题,这个问题的产生根源在于计算存储数字是二进制,对无限循环小 ...

  7. c# 取余数 浮点数_浮点数精度问题透析:小数计算不准确+浮点数精度丢失根源

    在知乎上上看到如下问题: 浮点数精度问题的前世今生? 1.该问题出现的原因 ? 2.为何其他编程语言,比如java中可能没有js那么明显 3.大家在项目中踩过浮点数精度的坑? 4.最后采用哪些方案规避 ...

  8. java long转object_Java 类型转换以及Object转成其他类型

    Object转int int count=(int)map.get("count") int count=Integer.parseInt((String)map.get(&quo ...

  9. BigDecimal类型一定不会失真吗?不一定。参数类型为double的构造方法的结果有一定的不可预知性,是有可能产生失真的。

    BigDecimal类型一定不会失真吗? 不一定. 参数类型为double的构造方法的结果有一定的不可预知性,是有可能产生失真的. public class Test1 {public static ...

  10. Think in Java第四版 读书笔记8第14章 类型信息(RTTI与反射)

    Java如何在运行时识别对象和类的信息? 1.RTTI(Run-time type information) 它假定我们在编译时已经知道了所有类型 2.反射 它允许我们在运行时发现和使用类的信息 14 ...

最新文章

  1. Linux软连接和硬链接
  2. IOS长按识别二维码失败
  3. Visual Studio 2010 Ultimate测试体系结构
  4. matlab fittype 求不出参数,[转]matlab 中fit fittype
  5. 【PAT乙级】1066 图像过滤 (15 分)
  6. SOC/LM在台湾的2011年发展趋势研判
  7. 算法篇---java经典问题!!!
  8. 隐马尔可夫模型,最大熵马尔可夫模型和条件随机场的区别与联系
  9. 金属100寸“电视”却无屏,语音识别+DTS+1080P,微鲸M1测评
  10. python官方文档中文版-主页 - Keras 中文文档
  11. 【转】Ubuntu常用软件合集
  12. 细胞制备流程图_体细胞核移植过程中,注入“供体细胞”还是“供体细胞核”?...
  13. python中append函数的用法
  14. 三星公司的开会流程--绝对值得一看
  15. mevan 的常用命令和参数解释
  16. Unity3D中角色撞击物体弹出提示框或显示对象效果
  17. win7计算机任务栏颜色怎么,如何修改win7电脑下方任务栏的颜色?
  18. RPC框架的意义和用法,什么是RPC
  19. 阿里云服务器ECS添加数据盘
  20. Linux系统/etc/fstab文件损坏如何处理

热门文章

  1. 24 React.createRef()用法细节分析
  2. 追寻终极数据库 - 事务/分析混合处理系统的交付挑战 (3)
  3. JAXB vs XStream
  4. 【翻译自mos中文文章】重建控制文件的方法
  5. R内存扩展 win7内存扩展
  6. 人工智能与图像传感器
  7. python矩阵相关操作
  8. deeplab运行指南
  9. 第5章 Python 数字图像处理(DIP) - 图像复原与重建8 - 估计噪声参数
  10. gitlab备份及恢复