Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
下我們將為大家介紹 JavaScript 保留兩位小數(shù)的實(shí)現(xiàn)方法:
四舍五入
以下處理結(jié)果會(huì)四舍五入:
var num=2.446242342; num=num.toFixed(2); // 輸出結(jié)果為 2.45
不四舍五入
以下處理結(jié)果不會(huì)四舍五入:
第一種,先把小數(shù)邊整數(shù):
Math.floor(15.7784514000 * 100) / 100 // 輸出結(jié)果為 15.77
第二種,當(dāng)作字符串,使用正則匹配:
Number(15.7784514000.toString().match(/^\d+(?:\.\d{0,2})?/)) // 輸出結(jié)果為 15.77,不能用于整數(shù)如 10 必須寫為10.0000
注意:如果是負(fù)數(shù),請(qǐng)先轉(zhuǎn)換為正數(shù)再計(jì)算,最后轉(zhuǎn)回負(fù)數(shù)
篇文章主要介紹了javascript實(shí)現(xiàn)保留兩位小數(shù)的多種不同效果,如果數(shù)字的原本小數(shù)位數(shù)不到兩位,那么缺少的就自動(dòng)補(bǔ)零,非常適用于商城類網(wǎng)站,感興趣的小伙伴們可以參考一下。一般可以用作全局方法調(diào)用。
(function (window) {
// 將小數(shù)點(diǎn)清零
var toInteger=function (value) {
value=Math.round(parseFloat(value));
return value;
};
// 保留一位小數(shù)點(diǎn)
var toDecimal=function (value) {
value=Math.round(parseFloat(value) * 10) / 10;
if (value.toString().indexOf(".") < 0) {
value=value.toString() + ".0";
}
return value;
}
// 保留兩位小數(shù)點(diǎn)
var toFloat=function (value) {
value=Math.round(parseFloat(value) * 100) / 100;
if (value.toString().indexOf(".") < 0) {
value=value.toString() + ".00";
}
return value;
}
// 保留兩位小數(shù)點(diǎn),一位小數(shù)自動(dòng)補(bǔ)零
var toZero=function (value) {
value=Math.round(parseFloat(value) * 100) / 100;
var xsd=value.toString().split(".");
//Ext.log(xsd.length);
if (xsd.length==1) {
value=value.toString() + ".00";
return value;
}
if (xsd.length > 1) {
if (xsd[1].length < 2) {
value=value.toString() + "0";
}
return value;
}
}
window.fomatFloat={
toInteger: toInteger,
toDecimal: toDecimal,
toFloat: toFloat,
toZero: toZero,
};
})(window);
使用方式:
console.log(fomatFloat.toInteger(1234.45678));
console.log(fomatFloat.toDecimal(1234.45678));
console.log(fomatFloat.toFloat(1234.45678));
console.log(fomatFloat.toZero(1234.45678));
console.log(fomatFloat.toZero(1234.1));
console.log(fomatFloat.toZero(1234));
運(yùn)行結(jié)果:
本文內(nèi)容均屬個(gè)人原創(chuàng)作品,轉(zhuǎn)載此文章須附上出處及原文鏈接。
加關(guān)注,定時(shí)推送,互動(dòng)精彩多,若你有更好的見解,歡迎留言探討!
責(zé)聲明:
我已經(jīng)盡量簡(jiǎn)化了,由于觀看本節(jié)內(nèi)容導(dǎo)致的頭暈、脫發(fā)、惡心、嘔吐等生理癥狀,本人概不負(fù)責(zé)
在現(xiàn)實(shí)世界中,小數(shù)的書寫方式非常自然,只需要使用.即可代表之后的數(shù)字全是小數(shù),例如3.1415926
但是計(jì)算機(jī)存儲(chǔ)小數(shù)的時(shí)候,麻煩就來了。
比如3.14,整數(shù)部分的二進(jìn)制是11,小數(shù)部分的二進(jìn)制是1011,合在一起就是111011,你能說這個(gè)數(shù)是3.14嗎?
問題的根源就在它難以準(zhǔn)確的表述小數(shù)點(diǎn)的位置。
因此,必須另尋他法。
浮點(diǎn)數(shù)基本概念
聰明的人想出了一個(gè)巧妙的辦法
在現(xiàn)實(shí)世界中,任何數(shù)字都可以表示為a.xxxx * 10^na.xxxx?10n,其中,a的取值范圍是1~9
這叫做科學(xué)計(jì)數(shù)法
比如:
1024.5678=1.0245678 * 10^31024.5678=1.0245678?103,它表示,1.0245678的小數(shù)點(diǎn)向右移動(dòng)3位,即最終的十進(jìn)制小數(shù)
952.7=9.527 * 10^2952.7=9.527?102,它表示,9.527的小數(shù)點(diǎn)向右移動(dòng)2位,即最終的十進(jìn)制小數(shù)
那二進(jìn)制是否也可以這樣表示呢?
當(dāng)然可以,在二進(jìn)制的世界中,任何數(shù)字(包括整數(shù))都可以表示為a.xxxx * 2^na.xxxx?2n,a只能取1
比如:
110.101=1.10101 * 2^2110.101=1.10101?22,它表示,1.10101的小數(shù)點(diǎn)向右移動(dòng)2位,即最終的二進(jìn)制小數(shù)
0010.00011=1.000011 * 2^10010.00011=1.000011?21,它表示,1.000011的小數(shù)點(diǎn)向右移動(dòng)1位,即最終
的二進(jìn)制小數(shù)
可以看出,二進(jìn)制如果也使用科學(xué)計(jì)數(shù)法,以下東西都是固定的:
底數(shù)2
整數(shù)部分1
而不固定的部分是:
指數(shù)部分
尾數(shù)部分(小數(shù)點(diǎn)后面的部分)
因此,我們可以使用下面的方式來表示一個(gè)數(shù)字
第一部分第二部分第三部分
符號(hào) 階碼 尾數(shù)
0為正,1為負(fù) 這部分表示指數(shù)部分 這部分表示小數(shù)點(diǎn)后面的部分
這種表示數(shù)字的方法,叫做浮點(diǎn)數(shù)表示法
比如,110.101=1.10101 * 2^2110.101=1.10101?22,改數(shù)字的符號(hào)是0,階碼是2,階碼的二進(jìn)制格式是10,尾數(shù)是10101,因此,在計(jì)算機(jī)中可以用浮點(diǎn)數(shù)表示為:
符號(hào)階碼尾數(shù)
0 10 10101
是不是很簡(jiǎn)單。
但這樣一來,容易導(dǎo)致CPU搞不清楚階碼和尾數(shù)是在哪里分割的,我們可以輕松的從表格中看出,但計(jì)算機(jī)哪有什么表格,它是存在一起的:01010101
為了解決這個(gè)問題,階碼和尾數(shù)的長(zhǎng)度就必須固定
比如,階碼的長(zhǎng)度規(guī)定為3,尾數(shù)的長(zhǎng)度規(guī)定為4,加上一個(gè)符號(hào)位,剛好是8位,一個(gè)字節(jié)
如果按照這種約定,計(jì)算機(jī)就可以輕松的取出第一個(gè)符號(hào)位,然后輕松的取出后三位階碼,繼續(xù)取出后四位的尾數(shù)
符號(hào)(1)階碼(3)尾數(shù)(4)
0 010 1010
可以看到,這種情況下,尾數(shù)的最后一位被丟棄了,從10101變成了1010,因?yàn)樗荒艽鎯?chǔ)4位。
所以,使用浮點(diǎn)數(shù)存儲(chǔ)數(shù)字時(shí),可能導(dǎo)致存儲(chǔ)的數(shù)字不精確
以上,就是浮點(diǎn)數(shù)存儲(chǔ)數(shù)字的方式。
數(shù)字到浮點(diǎn)數(shù)的轉(zhuǎn)換
我們知道,二進(jìn)制科學(xué)計(jì)數(shù)法是浮點(diǎn)數(shù)的基石,只要有了二進(jìn)制的科學(xué)計(jì)數(shù)法,就可以變成浮點(diǎn)數(shù)的存儲(chǔ)了。
然而,我們平時(shí)接觸更多的是十進(jìn)制的小數(shù)
現(xiàn)在的問題是:如何把十進(jìn)制的小數(shù)轉(zhuǎn)換為浮點(diǎn)數(shù)的科學(xué)計(jì)數(shù)法?
下面將一步一步進(jìn)行分析
二進(jìn)制小數(shù)到十進(jìn)制小數(shù)
要理解十進(jìn)制小數(shù)是如何轉(zhuǎn)換成二進(jìn)制小數(shù)的,就必須要先理解相反的情況:二進(jìn)制小數(shù)是如何轉(zhuǎn)換成十進(jìn)制小數(shù)的。
我們知道,任何一個(gè)十進(jìn)制的小數(shù)(包括整數(shù))都可以書寫為下面的格式:
21.25=2 * 10^1 + 1 * 10^0 + 2 * 10^{-1} + 2 * 10^{-2}21.25=2?101+1?100+2?10?1+2?10?2
二進(jìn)制的小數(shù)也可以用同樣的規(guī)則,只不過把底數(shù)10換成底數(shù)2
下面的示例就是把一個(gè)二進(jìn)制小數(shù)11.01轉(zhuǎn)換成了十進(jìn)制小數(shù)3.25:
11.01_2=1 * 2^1 + 1 * 2^0 + 0 * 2^{-1} + 1 * 2^{-2}=3.25_{10}11.012=1?21+1?20+0?2?1+1?2?2=3.2510
十進(jìn)制小數(shù)到二進(jìn)制小數(shù)
知道了二進(jìn)制小數(shù)轉(zhuǎn)十進(jìn)制,反過來也是一樣的
省略了具體的數(shù)學(xué)推導(dǎo)(數(shù)學(xué)好的朋友自行完成),我們按照下面的方式來轉(zhuǎn)換
比如十進(jìn)制數(shù)3.25
首先轉(zhuǎn)換整數(shù)部分:
3_{10}=11310=11
整數(shù)部分的轉(zhuǎn)換在之前的章節(jié)已經(jīng)說的很詳細(xì)了,不再重復(fù)
然后轉(zhuǎn)換小數(shù)部分
現(xiàn)有小數(shù)乘以2取整數(shù)部分
0.25 0.5 0
0.5 1 1
0 不再處理 不再處理
最終得到的二進(jìn)制小數(shù)部分是01,即把每次取整部分從上到下依次羅列即可
0.25_{10}=0.01_20.2510=0.012
把最終的整數(shù)部分加入進(jìn)去,就形成了
3.25_{10}=11.01_{2}3.2510=11.012
無法精確轉(zhuǎn)換
有的時(shí)候,這種轉(zhuǎn)換是無法做到精確的
比如0.3這個(gè)十進(jìn)制數(shù),轉(zhuǎn)換成二進(jìn)制小數(shù)按照下面的過程進(jìn)行
現(xiàn)有小數(shù)乘以2取整數(shù)部分
0.3 0.6 0
0.6 1.2 1
0.2 0.4 0
0.4 0.8 0
0.8 1.6 1
0.6 1.2 1
0.2 0.4 0
0.4 0.8 0
0.8 1.6 1
0.6 1.2 1
... ... ...
0.3_{10}=0.0 1001 1001 1001 1001 ...=0.0\overline{1001}0.310=0.01001100110011001...=0.01
在轉(zhuǎn)換的過程中,可能導(dǎo)致十進(jìn)制的現(xiàn)有小數(shù)永遠(yuǎn)無法歸零,于是轉(zhuǎn)換成了一個(gè)無限的二進(jìn)制小數(shù)。
同時(shí),計(jì)算機(jī)無法存儲(chǔ)一個(gè)無限的數(shù)據(jù),因此,總有一些數(shù)據(jù)會(huì)被丟棄,這就造成了計(jì)算機(jī)存儲(chǔ)的小數(shù)部分可能是不精確的
進(jìn)一步,如果一個(gè)小數(shù)無法精確的存儲(chǔ),那么他們之間的運(yùn)算結(jié)果也是不精確的
這就是計(jì)算機(jī)對(duì)小數(shù)的運(yùn)算不精確的原因
// js語(yǔ)言中運(yùn)行5.3 - 5.2 // 得到0.09999999999999964
轉(zhuǎn)換成二進(jìn)制的科學(xué)計(jì)數(shù)
現(xiàn)在,按照以上所述的規(guī)則,我們已經(jīng)可以輕松的把一個(gè)十進(jìn)制的數(shù)字轉(zhuǎn)換成二進(jìn)制格式了
然后,我們?cè)僭谒幕A(chǔ)上,把它變化為二進(jìn)制的科學(xué)計(jì)數(shù)格式
3.25_{10}=11.01_2=1.101 * 2^13.2510=11.012=1.101?21
注意,1.101 * 2^11.101?21是二進(jìn)制的科學(xué)計(jì)數(shù)表示,你并不能把它當(dāng)成十進(jìn)制的方式運(yùn)算,如果你要將其轉(zhuǎn)換成十進(jìn)制,應(yīng)該:
將1.101的小數(shù)點(diǎn)向右移動(dòng)1位,得到11.01
.01=1
2^1 + 1
2^0 + 0
2^{-1} + 1
2^{-2}=3.25$
當(dāng)我們拿到這個(gè)數(shù)的二進(jìn)制科學(xué)計(jì)數(shù)后,就可以輕松的將其存儲(chǔ)下來了
3.25=11.01=1.101 * 2^1=1.1010 * 2^13.25=11.01=1.101?21=1.1010?21的存儲(chǔ)
因?yàn)槲矓?shù)是4位,所以不足在后面補(bǔ)0
符號(hào)(1)階碼(3)尾數(shù)(4)
0 001 1010
然而
請(qǐng)?jiān)试S我做一個(gè)悲傷的表情
還有一種情況沒有考慮到...
指數(shù)偏移量
建議先讀完本節(jié)內(nèi)容,然后再反復(fù)推理和思考
我們來聊一聊還有什么情況沒有考慮到
現(xiàn)在,我們有一個(gè)十進(jìn)制的數(shù)字0.25,它轉(zhuǎn)換成二進(jìn)制的格式應(yīng)該是0.01,科學(xué)計(jì)數(shù)法表示的結(jié)果是1*2^{-2}1?2?2,即小數(shù)點(diǎn)應(yīng)該向左移動(dòng)2位
現(xiàn)在的問題是,指數(shù)部分出現(xiàn)了負(fù)數(shù)!
注意,不是數(shù)字是負(fù)數(shù),是指數(shù)是負(fù)數(shù)
問題在于,我難道對(duì)指數(shù)也要使用一個(gè)符號(hào)位來處理負(fù)數(shù)的情況嗎?
實(shí)際上沒有必要,在計(jì)算機(jī)運(yùn)算浮點(diǎn)數(shù)時(shí),對(duì)于指數(shù)部分,更多的操作是比較,即比較兩個(gè)指數(shù)哪個(gè)大
如果使用符號(hào)位的話,在比較時(shí)就必須考慮符號(hào)的問題,這樣會(huì)給比較帶來很多麻煩
因此,IEEE 754規(guī)定,使用指數(shù)偏移量來處理這個(gè)問題
IEEE 754是對(duì)浮點(diǎn)數(shù)存儲(chǔ)、運(yùn)算的國(guó)際標(biāo)準(zhǔn),絕大部分計(jì)算機(jī)語(yǔ)言的浮點(diǎn)數(shù)都遵循該標(biāo)準(zhǔn)
它規(guī)定,如果一個(gè)浮點(diǎn)數(shù)的指數(shù)位數(shù)為ee,則它的指數(shù)偏移量為2^{e - 1} - 12e?1?1,不管存儲(chǔ)什么指數(shù)值,都需要加上這個(gè)偏移量后再進(jìn)行存儲(chǔ)。
比如,指數(shù)的位數(shù)是3,則指數(shù)的偏移量為2^{3-1} - 1=323?1?1=3,當(dāng)存儲(chǔ)指數(shù)-2時(shí),需要加上偏移量3再進(jìn)行存儲(chǔ),因此,指數(shù)-2實(shí)際上存儲(chǔ)的是1,即001
再比如,當(dāng)存儲(chǔ)指數(shù)2時(shí),需要加上偏移量3再進(jìn)行存儲(chǔ),因此,指數(shù)2實(shí)際上存儲(chǔ)的是5,即101
如果比較-2和2哪個(gè)大,就直接比較兩個(gè)二進(jìn)制即可,001顯然比101要小,指數(shù)部分完全沒有符號(hào)位,這樣比較起來就輕松多了。
當(dāng)然,當(dāng)需要還原它的真實(shí)指數(shù)時(shí),只需要減去偏移量即可
于是,有了這樣的規(guī)則后:
0.25_{10}=0.01_2=1.0000 * 2^{-2}0.2510=0.012=1.0000?2?2
符號(hào)(1)階碼(3)尾數(shù)(4)
0 001 0000
3.25_{10}=11.01_2=1.1010 * 2^13.2510=11.012=1.1010?21
符號(hào)(1)階碼(3)尾數(shù)(4)
0 100 1010
由于有了偏移量的存在,浮點(diǎn)數(shù)的指數(shù)范圍就可以很輕松的算出來了
最小能存儲(chǔ)的指數(shù)是000,減去偏移量后真實(shí)的指數(shù)是-3
最大能存儲(chǔ)的指數(shù)是111,減去偏移量后真實(shí)的指數(shù)是4
稍微的總結(jié)一下,就是:
階碼為n位的浮點(diǎn)數(shù),指數(shù)的真實(shí)范圍是-2^{n-1}+1?2n?1+1 到 2^{n-1}2n?1
特殊值
在浮點(diǎn)數(shù)的標(biāo)準(zhǔn)中,有下面兩個(gè)特殊值:
NaN:Not a Number,表示不是一個(gè)數(shù)字,它通常來自一些錯(cuò)誤的運(yùn)算,比如
3.14 * "你好"
Infinity:正向的無窮大,相當(dāng)于數(shù)學(xué)中的
\infty
∞
-Infinity:負(fù)向的無窮大,相當(dāng)于數(shù)學(xué)中的
-\infty
?
∞
為了表示這三個(gè)值,IEEE 754標(biāo)準(zhǔn)規(guī)定,當(dāng)使用一種特殊的數(shù)字存儲(chǔ)來表示:
NaN
符號(hào)(1)階碼(3)尾數(shù)(4)
無所謂
比如:
符號(hào)(1)階碼(3)尾數(shù)(4)
0 111 1010
上面這個(gè)數(shù)字可不是1.1010*2^{4}1.1010?24,它是一個(gè)NaN
無窮
符號(hào)(1)階碼(3)尾數(shù)(4)
0:正無窮,1:負(fù)無窮 111
比如:
符號(hào)(1)階碼(3)尾數(shù)(4)
0 111 0000
上面這個(gè)數(shù)字可不是1.0000*2^{4}1.0000?24,它是一個(gè)Infinity
由于特殊值的存在,讓階碼的最大值用于表示特殊值,因此,正常的數(shù)字階碼是不能取到最大值的
因此,正常數(shù)字的階碼取值范圍少了一個(gè):-2^{n-1}+1?2n?1+1 到 2^{n-1} - 12n?1?1
比如,3位的階碼,它能表示的正常指數(shù)范圍是-3到3
單精度和雙精度
很多計(jì)算機(jī)語(yǔ)言中都有單精度和雙精度的概念,它們的區(qū)別在于階碼和尾數(shù)的位數(shù)是不一樣的
Java的float是單精度浮點(diǎn)數(shù),double是雙精度浮點(diǎn)數(shù)
JS的所有數(shù)字均為雙精度浮點(diǎn)數(shù)
類型符號(hào)階碼尾數(shù)共計(jì)
單精度 1位 8位 23位 32bit,4byte
雙精度 1位 11位 52位 64bit,8byte
總結(jié)
由于浮點(diǎn)數(shù)這種特別的存儲(chǔ)方式,因此,不同的階碼和尾數(shù)的位數(shù),決定了:
階碼位數(shù)越多,可以取到的指數(shù)越大,因此可以表示的數(shù)字越大
尾數(shù)位數(shù)越多,可以表示的數(shù)字位數(shù)越多,因此可以表示的更加精確
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。