一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - C/C++ - C++中double浮點數精度丟失的深入分析

C++中double浮點數精度丟失的深入分析

2021-10-18 14:18adanus C/C++

這篇文章主要給大家介紹了關于C++中double浮點數精度丟失的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

看了一篇關于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<iostream>
#include<stdlib.h>

void showEncodeOfDouble(unsigned char* db){

 const int ByteLength=8; 
 for(int i=ByteLength-1;i>=0;i--) 
  printf(" %.2x",db[i]);

 printf("\n");

}


int main(){
 
 unsigned long 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((unsigned char*)&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浮點標準,它以“二進制的科學表示法”表示一個小數:

C++中double浮點數精度丟失的深入分析

其中M是一個整數部分僅有一位的二進制小數,例如1.011,表示十進制下的1.375。E表示該小數以2為底時的階數。基于以上的表示方式,小數需要對三部分進行編碼:表示符號的s,及階碼E、尾數碼M。C++中的double類型三種編碼所占的位數如圖所示。

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數值為

C++中double浮點數精度丟失的深入分析

2)若e=0,則小數值為

C++中double浮點數精度丟失的深入分析

那么,可以看函數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語言標準沒有對這種情況指出固定的結果,這種轉換行為是無定義的。

參考鏈接:

[1] http://en.wikipedia.org/wiki/Double-precision_floating-point_format#cite_note-whyieee-1

[2]深入理解計算機系統,Randal E. Bryant, 機械工業出版社

[3]http://stackoverflow.com/questions/4738768/printing-double-without-losing-precision

到此這篇關于C++中double浮點數精度丟失的深入分析的文章就介紹到這了,更多相關C++ double浮點數精度丟失內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!

原文鏈接:https://www.cnblogs.com/cai2007/p/3679443.html

延伸 · 閱讀

精彩推薦
  • C/C++C語言中炫酷的文件操作實例詳解

    C語言中炫酷的文件操作實例詳解

    內存中的數據都是暫時的,當程序結束時,它們都將丟失,為了永久性的保存大量的數據,C語言提供了對文件的操作,這篇文章主要給大家介紹了關于C語言中文件...

    針眼_6702022-01-24
  • C/C++C語言實現電腦關機程序

    C語言實現電腦關機程序

    這篇文章主要為大家詳細介紹了C語言實現電腦關機程序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下...

    xiaocaidayong8482021-08-20
  • C/C++詳解c語言中的 strcpy和strncpy字符串函數使用

    詳解c語言中的 strcpy和strncpy字符串函數使用

    strcpy 和strcnpy函數是字符串復制函數。接下來通過本文給大家介紹c語言中的strcpy和strncpy字符串函數使用,感興趣的朋友跟隨小編要求看看吧...

    spring-go5642021-07-02
  • C/C++C/C++經典實例之模擬計算器示例代碼

    C/C++經典實例之模擬計算器示例代碼

    最近在看到的一個需求,本以為比較簡單,但花了不少時間,所以下面這篇文章主要給大家介紹了關于C/C++經典實例之模擬計算器的相關資料,文中通過示...

    jia150610152021-06-07
  • C/C++c++ 單線程實現同時監聽多個端口

    c++ 單線程實現同時監聽多個端口

    這篇文章主要介紹了c++ 單線程實現同時監聽多個端口的方法,幫助大家更好的理解和學習使用c++,感興趣的朋友可以了解下...

    源之緣11542021-10-27
  • C/C++深入理解goto語句的替代實現方式分析

    深入理解goto語句的替代實現方式分析

    本篇文章是對goto語句的替代實現方式進行了詳細的分析介紹,需要的朋友參考下...

    C語言教程網7342020-12-03
  • C/C++學習C++編程的必備軟件

    學習C++編程的必備軟件

    本文給大家分享的是作者在學習使用C++進行編程的時候所用到的一些常用的軟件,這里推薦給大家...

    謝恩銘10102021-05-08
  • C/C++C++之重載 重定義與重寫用法詳解

    C++之重載 重定義與重寫用法詳解

    這篇文章主要介紹了C++之重載 重定義與重寫用法詳解,本篇文章通過簡要的案例,講解了該項技術的了解與使用,以下就是詳細內容,需要的朋友可以參考下...

    青山的青6062022-01-04
主站蜘蛛池模板: 国色天香视频完整版 | 国产成人一区二区三区在线视频 | 丰满的闺蜜2中文字幕 | 国产一级视频在线观看 | 精品国产一区二区三区在线 | 私人chinese beauty | 女子校生下媚药在线观看 | 欧美日韩一区二区综合在线视频 | 国产裸舞福利资源在线视频 | 欧美精品亚洲精品日韩1818 | 99精品久久久久久 | 欧美腐剧mm在线观看 | 国产成人a v在线影院 | juliaann大战黑人 | 好大好硬视频 | 色老女人| 欧美大片一区二区 | 午夜精品久久久久久久99蜜桃 | 99久久免费国产香蕉麻豆 | 日本成人免费在线视频 | 天美影视文化传媒mv免费 | 40分钟在线观看免费 | 国内精品一区视频在线播放 | 国产成人精品午夜视频' | 国产一卡2卡3卡4卡公司科普 | 2021国产精品视频 | 日本wwxx| 日本在线亚州精品视频在线 | 国产绳艺在线播放 | 国产精品刺激好大好爽视频 | 午夜免费无码福利视频麻豆 | 香蕉国产人午夜视频在线 | 毛片资源站| 日本国产高清色www视频在线 | 日韩aⅴ在线观看 | 无限资源在线观看完整版免费下载 | 国产成人在线视频播放 | kayden·kross hd在线| 无人影院在线播放 | 精品国产一区二区三区久 | 极品奶妈漫画 |