問題出自乙個**的轉換需要將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 命令列,本文不是介紹某些命令的用法,而是說明一些簡單卻特別容易讓...