簡體   English   中英

浮點數中整數的精確表示

[英]Exact representation of integers in floating points

我試圖了解浮點格式的整數表示形式。

由於IEEE浮點格式的尾數只有23位,我希望任何大於1 << 22的整數都只是一個近似表示。 這不是我在g ++中觀察到的

下面的兩個cout都打印相同的值33554432。

由於尾數部分是負責精度的部分,我們如何能夠表示(存儲)需要超過23位才能准確存儲的精確數字。

void floating_point_precision(){
  cout<< setprecision(10);
  float fp = (1<<25);
  cout<< fp <<endl;
  cout<< (1<<25) <<endl;
}

作為基於以下答案的后續操作,即使兩個fp,i的打印內容都不相同,以下代碼為何仍未執行“不等於”操作?

void floating_point_precision(){
  cout<< setprecision(10);
  float fp = ((1<<25)+1);
  cout<< fp <<endl;
  int i = ((1<<25)+1)  ;
  cout<< i <<endl;
  if(i != fp)
    cout<< "Not equal" <<endl;
}

的確,IEEE浮點只有有限數量的尾數位。 如果有23個尾數位,則它可以准確表示2個23個不同的整數值。

但是由於浮點數分別存儲2的冪次冪,因此它可以(受限於有限的指數范圍)精確表示2個23乘以 2 的冪

33554432正好是2 25 ,因此只需要一個尾數位即可准確表示它(加上一個二進制指數,表示乘以2的冪)。 它的二進制表示形式是10000000000000000000000000 ,它具有26位,但只有1個有效位。 (嗯,實際上它們都很重要,但是您明白了。)

您會發現它的相鄰整數值3355443133554433 無法准確地用32位float (但是它們可以用64位double 。)

更一般而言, float類型的可連續表示的值之間的差異隨該值的大小而變化。 在我的系統上(大多數系統使用IEEE格式,但是標准不需要),請使用以下程序:

#include <iostream>
#include <iomanip>
#include <cmath>

void show(float f) {
    std::cout << std::nextafterf(f, 0.0) << "\n"
              << f << "\n"
              << std::nextafterf(f, f*2) << "\n";
    putchar('\n');
}

int main(void) {
    std::cout << std::setprecision(24);

    show(1);
    show(1<<23);
    show(1<<24);
    show(1<<30);
}

產生以下輸出:

0.999999940395355224609375
1
1.00000011920928955078125

8388607.5
8388608
8388609

16777215
16777216
16777218

1073741760
1073741824
1073741952

它以數字float形式顯示數字1、2 23、2 24和2 30的直接前任和后繼。 如您所見,數字越大,差距越大,每乘以2的次方,差距的大小就會增加一倍。

您將獲得類似的結果,但使用doublelong double類型的間隙較小。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM