你必須知道的 double轉換int的問題

2021-09-26 09:02:21 字數 1755 閱讀 5471

問題出自乙個**的轉換需要將double型別轉換(元)為integer型別(單位分)的數.

$saleprice

=10.2

;$price

=(int)

($saleprice

*100);

// 1019

雖然少了一分錢,但是對於這種問題的嚴重性,每個使用者少付款一分錢,雖然說平台使用者少,但對於對賬會觸發報警,甚至不能下單因為實際付款額與售價不等.

接下來我們先從計算機如何儲存二進位制數字說起.

整數部分 --> 轉為二進位制

小數點不動

小數部分 --> 轉為二進位制

這裡重點說下:小數部分轉換

0.25轉換為二進位制如下:

0.25 * 2 = 0.5   // 0 取整數字如果為1取1,這裡為0取0,小數部分不為0所以 拿0.5去下一步

0.5*2 =1.0 // 1 小數部分為0 結束計算

10.25就可以表示為 1010.01

小數部分轉換:

0.25

↓0 1

得出小數部分演算法

0*2^ +  1*2^
眾所周知,php使用c語言實現,浮點型別在zval中是double.

符號位     11位 指數      52位尾數

0 0000 0000 000 000.....000

以10.25為例:

1010.01 => 轉換為

1.01001 * 2^
中間數:為了表示負指數,所以提出了乙個中間數的概念. 中間數:2^n-1 n為指數字數.

所以double型別的中間數為1023, 而float型別為127.

例如指數為-7那麼, 127 + (-7)= 120 -> 01111000,讀取時候還得減去127,得出真實值.

中間數可以理解為乙個符號位,表示指數的符號.

中間數全為1,尾數字為全為0表示無窮大

中間數全為1,尾數字不全為0表示nan

中間數全為0,尾數字全為0表示0

因此得到記憶體模型為:

符號位     11位 指數      52位尾數字

0 1000 0000 011 01001 0......000

從記憶體模型當中讀取資料時:

符號位     11位 指數                              52位尾數字

0 1000 0000 011 01001 0......000

+ 130-127 = 0000 0000 011= 3

尾數字前補1和. => 1.01001

將小數點右移指數字個數(減去中間數後如果指數字最低位為1則左移) => 1010.01

按照二進位制轉十進位制規則得出:10.25

php中可以使用bcmath庫,避免精度丟失.

兩數相乘可以用bcmul這個函式.

(int)bcmul(10.2, 100) =>  1020
使用bccomp準確比較兩個任意精度型別.

其他語言參照相關的庫,c語言中也有bcmath庫的實現.

Linux世界你必須知道的

突然從windows世界轉向linux世界,也許剛開始或多或少都有點不太適應,慢慢地,也許你會發現linux的博大精深,最重要的是linux世界的很多東西都是free license,下面列舉一下linux世界你需要或必須知道的二三事。unix like 叫做 類unix 系統,主要指各種各樣的li...

你必須知道的關於tcp keepalive 設定

1.引數設定 檢視相關的引數 sysctl a grep tcp keepalive net.ipv4.tcp keepalive intvl 30 net.ipv4.tcp keepalive probes 2 net.ipv4.tcp keepalive time 160 設定相關的引數 sys...

關於 Linux shell 你必須知道的

我個人很喜歡使用 linux 系統,雖然說 windows 的圖形化介面做的確實比 linux 好,但是對指令碼的支援太差了。一開始有點不習慣命令列操作,但是熟悉了之後反而發現移動滑鼠點點點才是浪費時間的罪魁禍首。那麼對於 linux 命令列,本文不是介紹某些命令的用法,而是說明一些簡單卻特別容易讓...