首頁>Club>
6
回覆列表
  • 1 # 使用者5721302084144

    python裡7/3的值為什麼會是2.3333333333333335,末位為什麼會是5?

    短回答:

    因為浮點數的精度問題。

    長回答:

    7/3 結果是一個無限迴圈小數,而對於計算機,無限迴圈小數是無法儲存的,要進行截斷處理。

    你可能會問四捨五入的話應該是2.3333333333333333才對啊,結尾怎麼會是5呢?

    其實,這裡的截斷處理是指在計算機浮點數表示法裡進行截斷,以64位浮點數為例,有1位表示正負,11位表示指數,52位表示尾數。

    計算機所做的事情,是計算 7/3 的值,直到52位尾數全部佔滿位以後停止,也就是截斷。

    7/3 計算後為10.010101010101010101010101010101010101010101010101011,轉化為十進位制後就是2.3333333333333335,末尾出現5就不奇怪了。

    PS:

    在python3中,7/3的計算結果以浮點數來表示,為2.3333333333333335。

    在python2中,7/3的計算結果以整數來表示,為2.

    最後給題主加把勁兒!

    回覆細心的 @張博宇 提到的問題:

    一、10.01010....011,沒數錯的話似乎是53位數字(反正肯定是奇數位),而不是偶數位?二、為什麼截斷的末尾是01011,而不是01010?三、1.0/3,結果是0.33333...33,最後一位是3,是不是因為Python的二進位制最後截斷是0.01010101...0101?

    首先指出一處小錯誤:一中不是53位,是51位。

    開始答題:

    我們來親手算一下。7/3,在這裡我們暫時把二進位制小數點算到53位以更清晰地說明問題:

    好戲要開始了,我們把上面這個能看花眼的二進位制小數轉化為科學記數法:

    注意,由於左移了一位小數點,這時候小數點後有54位。

    在64位浮點數中:

    1位符號為正,表示為‘0’;11位指數(小數點位移量)為1,表示為‘10000000000’;52位尾數為‘0010101010101010101010101010101010101010101010101011‘為什麼:尾部多出兩位’10‘無法保留,所以0舍1入,在第52進一位,所以第52位的0變為1.

    合起來,變為:

    這也是計算機在記憶體中儲存的方法。

    那麼讀取的時候就要把它再拆過來:

    在尾數0010101010101010101010101010101010101010101010101011前面加上‘1.’: 指數為10000000000,即1,小數點右移1位: 注意此時小數點後有51位,這裡回答了第一個問題為什麼末尾是01011和第二個問題為什麼是奇數。符號為0,數字為正;

    轉化為十進位制,即2.3333333333333335.

    第三個問題:1.0/3:

    二進位制定點數為:0.1010101010101010101010101010101010101010101010101010

    符號為正,表示為‘0‘;指數為-1(0.1010……變為01.010……),表示為’11111111110‘;尾數表示為’0101010101010101010101010101010101010101010101010101‘注意第52位為1,因為其本身就是1,第52位為0所以截斷時未發生進位。合起來:0111111111100101010101010101010101010101010101010101010101010101

    換成十進位制為0.3333333333333333.

    PS:

    感謝 @楊鑫逸 在我忙的時候幫我圓了場。

    如果有1000本《哈姆雷特》,那麼就有1000位莎士比亞。

    本莎士比亞哦不,本菜鳥所用方法出自弗羅贊《計算機科學導論(第三版)》第三章’資料儲存‘,若有錯誤請及時提醒。

    感謝 @msoeg 的提醒:

    64位浮點數轉為十進位制後有效數字為16位,所以第17位是不準確的。

    在這裡向知友們提出一個思考題:

    0.1+0.2 == 17位有效數字;

    而0.1+0.7 == 16位有效數字。

    這是為什麼?

    十進位制如何轉二進位制?

    首先弄清楚:十進位制3在二進位制是11,沒錯。但是十進位制0.3在二進位制就不是0.11了。

    在這裡為了更好地說明問題,我們取‘22.33’來做實驗。

    十進位制小數轉化為二進位制小數有兩部分:整數部分22和小數部分0.33。

    先來處理整數部分‘22’:

    源為22,底為2,目標暫為空。用底除源,商11餘0. 目標為‘0’,新源為11.用底除源,商5餘1,目標為‘10’,新源為5.用底除源,商2餘1,目標為‘110’,新源為2.用底除源,商1餘0,目標為‘0110’,新源為1.用底除源,商0餘1,目標為‘10110’,結束。

    二進位制整數部分為‘10110’。

    再來處理小數部分‘0.33’:

    源為0.33,底為2,目標暫為空,我們把目標位數定為7位。用底乘源,得0.66,目標為‘0’,新源為0.66.用底乘源,得1.32,目標為‘01’,新源為0.32.用底乘源,得0.64,目標為‘010’,新源為0.64.用底乘源,得1.28,目標為‘0101’,新源為0.28.用底乘源,得0.56,目標為‘01010’,新源為0.56.用底乘源,得1.12,目標為‘010101’,新源為0.12.用底乘源,得0.24,目標為‘0101010’,結束。

    二進位制整數部分為0.0101010.

    合起來:

    得10110.0101010

    PS:

    此方法出自弗羅贊《計算機科學導論(第三版)》第二章‘數字系統‘,若有錯誤請及時提醒。

    這種技術性回答有那麼多人瀏覽,有點出乎意料。

    所以,滿足一下我滴好奇心:你們為什麼點進來看這種‘枯燥’的技術問題?

  • 中秋節和大豐收的關聯?
  • 個案服務中怎樣與案主建立良好專業關係?