java long double精度丢失_long long类型转double类型部分精度丢失问题

我最近做了一道题,一个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浮点标准,它以“二进制的科学表示法”表示一个小数:

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

0818b9ca8b590ca3270a3433284dd417.png

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数值为

0818b9ca8b590ca3270a3433284dd417.png

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

0818b9ca8b590ca3270a3433284dd417.png

那么,可以看函数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, 机械工业出版社

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/264578.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从服务器上自动更新系统补丁

对于经常重系统的用户或公司,每次安装系统后,必须得从微软网站上面下载补丁,这样很浪费时间. 如何从自己服务器上自动更新系统补丁,方法如下: 服务器端 服务器端需要安装一个更新服务器软件,如:SUS (下载地址http://www.onlinedown.net/soft/35844.htm) 客户端设置 开始 -- 运行…

搭建于 Cubieboard 之上的超小型实时监控平台 - mjpg篇

2019独角兽企业重金招聘Python工程师标准>>> 运行于 Cubieboard开发板 之上的个人笔记博客 http://cb.e-fly.org:81/archives/system-camera-monitor-mjpg-streamer.html 原文作者:Cannikin原文链接:http://forum.cubietech.com/forum ... p…

java 判断一个字符串是否由数字组成的_Java中怎样判断一个字符串是否是数字

展开全部1.使用Character.isDigit(char)判断String str "123abc";if (!"".equals(str)) {char num[] str.toCharArray();//把字符串转换为字符数组StringBuffer title new StringBuffer();//使用StringBuffer类,把非数e69da5e887aa323131333…

博客园的BLOG也申请了

BLOG申请了不少,但还没定居过------大都不怎么满意. 希望这回能让我安定下来... 20150413转载于:https://www.cnblogs.com/lxwy/archive/2008/05/28/4420771.html

Docker 入坑教程笔记

Docker 入坑教程笔记 视频网址B站:点这里 查询命令 man docker 简单启动和退出 docker run --name [容器名] -i -t ubuntu /bin/bash 交互启动虚拟机-t 提供伪tty终端docker ps [-a][-l]docker inspect [container name or id] 配置信息,有用数据docker …

安卓开发工具

Android 下载需要用到的工具:(1)下载JAVA的IDE开发工具– Eclipse到Eclipse官方网站下载Ecplise For Java EE的最新Windows版本 下载Ecplise(2)下载Java开发包 — Java SE Development Kit (JDK) JDK 6到Sun官方网站下载JDK6,选择JDK 6 Update 12 下载JDK6(3)下载Android开发包…

java http 返回码_【Java】Http返回状态码

来自HttpStatus,记录一下CONTINUE(100, "Continue"),SWITCHING_PROTOCOLS(101, "Switching Protocols"),PROCESSING(102, "Processing"),CHECKPOINT(103, "Checkpoint"),OK(200, "OK"),CREATED(201, "Creat…

启明星辰招聘

呵,好简单的工作。一狠心一咬牙不去了....... 不如现在的工作环镜好。岗位名称:安全工程师 人数:4工作地点:北京 薪水范围:4000-8000元/月投递简历邮箱:hrvenustech.com.cn公司网站:www.venuste…

515. 在每个树行中找最大值

您需要在二叉树的每一行中找到最大的值。 示例&#xff1a; 输入: 1/ \3 2/ \ \ 5 3 9 输出: [1, 3, 9]在真实的面试中遇到过这道题&#xff1f;class Solution {public List<Integer> largestValues(TreeNode root) {List<Integer> res new ArrayList&l…

加密的一些概念

明文&#xff1a;可以被人或程序识别的数据。例如一个文本文件、一段歌词、一个Word文档、一首MP3、一个图片文件、一段视频等等。 加密算法&#xff1a;将数据搞乱掉的方法。 密钥&#xff08;密码&#xff09;&#xff1a;一个你在进行加密操作时给出的字符串&#xff0c;让加…

java有装箱和拆箱吗_Java中装箱和拆箱,你真的都懂么?

在给部门做分享的时候&#xff0c;一位同学提问说一直没搞明白Java的装箱和拆箱&#xff0c;让我给讲解下&#xff0c;所以才有了下面这篇文章&#xff1a;本次文章根据PPT分享整理而成&#xff0c;会有5点&#xff1a;1、什么是装箱和拆箱&#xff1f;2、基本数据类型和包装类…

架构-浅谈MySQL数据库优化

主从复制博文&#xff1a;http://lizhenliang.blog.51cto.com/7876557/1290431 读写分离博文&#xff1a;http://lizhenliang.blog.51cto.com/7876557/1305083 MySQL-MMM博文&#xff1a;http://lizhenliang.blog.51cto.com/7876557/1354576 &#xff08;一&#xff09;数据库部…

项目发布相关

1.证书 cer文件需要上传电脑CSR文件&#xff0c;所以其他电脑如需使用需要创建者导出&#xff0c;用于在项目在真机运行或archive的时候签名&#xff0c;Code Signing Identity. 项目App ID&#xff0c;Provisioning Profile只要有管理员权限就可以申请&#xff0c;与cer文件对…

端午随笔

今天是端午节&#xff0c;我也毕业了正式开始了工作生涯&#xff0c;四年的大学生活画上了句号。面临我是什么&#xff0c;我该何去何从。人生的道路已经脱离自己在大学期间的人生规划。新的开始&#xff0c;就要有新的计划。我在一家公司已经实习了三个月了&#xff0c;我是我…

java base64解码出错_Java Base64解码错误及解决方法

问题提出&#xff1a;自己在做一个小网站充当练手&#xff0c;但是前端图片经过base64加密后传往后端在解码。但是一直都有问题&#xff0c;请大神赐教public static string base64toimg(string src) throws ioexception {string uuid uuid.randomuuid().tostring();stringbui…

PPT图片内嵌文字效果

【摘要】在报纸杂志上我们经常看到&#xff0c;有些图片中可以嵌入文字&#xff0c;如下图所示的效果&#xff1a;今天我们一起来学习一下这种效果是怎样生成的。 【正文】以下的操作步骤为PowerPoint 2013版本。 一 插入图片并编辑图片在【插入-联机图片】中搜索需要的图片。…

[天地君亲若追问 枉为知音百年羞]2008.06.07 晃荡在芳华

洞房悄悄静悠悠&#xff0c;花烛高烧暖心头&#xff0c; 喜气阵阵难抑止&#xff0c;这姻缘百折千磨方成啊就。 三月来&#xff0c;屡托刘兄把亲求&#xff0c;每遭见拒愿难酬&#xff0c; 从此我诗书五经无心看&#xff0c;三餐茶饭懒下喉&#xff0c; 日卧书斋愁脉脉&#xf…

[BZOJ1297/Luogu4159][SCOI2009]迷路

题目链接&#xff1a; BZOJ1297 Luogu4159 首先考虑距离只有\(0,1\)的情况 那么如果设\(f[t][i][j]\)表示\(i\)到\(j\)走\(t\)时刻的方案数&#xff0c;有转移方程&#xff1a; \(f[t][i][j]\sum f[t-1][i][k]*f[t-1][j][k]\) 如果把\(f[t]\)看成一个\(n*n\)的矩阵就是\(f[t]f[…

java中的getfirst_Java LinkedList getFirst()用法及代码示例

Java.util.LinkedList.getFirst()方法用于从LinkedList或列表开头的元素中获取或检索第一个元素。用法:LinkedList.getFirst()参数&#xff1a;此方法不带任何参数。返回值&#xff1a;此方法返回第一个元素或列表开头的元素。以下示例程序旨在说明Java.util.LinkedList.getFir…

mybatis数据库数据分页问题

http://www.cnblogs.com/jcli/archive/2011/08/09/2132222.html 借花献佛&#xff0c;天天进步