2012-04-04 92 views
35

我正在使用javascript綁定到某些複選框,並且toFixed(2)未四捨五入。任何想法,爲什麼它不是四捨五入?例如,如果號碼是859.385,它只顯示859.38而不是859.39Javascript tofixed Not Rounding

我也讀過toFixed可以取決於你使用的瀏覽器有所不同,任何人都知道這種方式,以便我的JavaScript計算符合我的PHP計算嗎?

var standardprice = parseFloat($('#hsprice_'+this.id.split('_')[1]).val()); 
var price = parseFloat($('#hprice_'+this.id.split('_')[1]).val()); 
var discount = parseFloat($('#hdiscount_'+this.id.split('_')[1]).val()); 
var deposit = parseFloat($('#hdeposit_'+this.id.split('_')[1]).val()); 

var currSprice = parseFloat($('#hTotalSprice').val()); 
var currPrice = parseFloat($('#hTotalPrice').val()); 
var currDiscount = parseFloat($('#hTotalDiscount').val()); 
var currDeposit = parseFloat($('#hTotalDeposit').val()); 

currSprice += standardprice; 
currPrice += price; 
currDiscount += discount; 
currDeposit += deposit; 

$('#lblTotalSprice').text('$'+addCommas(currSprice.toFixed(2))); 
$('#lblTotalPrice').text('$'+addCommas(currPrice.toFixed(2))); 
$('#lblTotalDiscount').text('$'+addCommas(currDiscount.toFixed(2))); 
$('#lblTotalDeposit').text('$'+addCommas(currDeposit.toFixed(2))); 

$('#hTotalSprice').val(currSprice.toFixed(2)); 
$('#hTotalPrice').val(currPrice.toFixed(2)); 
$('#hTotalDiscount').val(currDiscount.toFixed(2)); 
$('#hTotalDeposit').val(currDeposit.toFixed(2)); 
+0

由於0.5正好在0和1之間,所以四捨五入只是一個約定,我想知道確保一個特定結果的真正重要性。另一方面,爲了測試你的代碼,你需要可預測的結果,測試很重要,所以這是一個很好的理由。 – 2014-05-09 17:44:45

+0

這裏提示爲什麼'.toFixed'舍入看起來很不直觀:'(0.1).toFixed(20)'。(請注意,IE的實現給出了「直觀」的結果,而其他瀏覽器給出了符合標準的值。) – Noyo 2015-05-17 20:30:57

+0

我對這裏的類似問題的回答是:http://stackoverflow.com/a/37751946/2261514 – Pawel 2016-06-10 15:45:04

回答

3

您可以使用Math.round()四捨五入數字。如果你想圓一個特定的小數點,你可以聘請一些數學:

var result=Math.round(original*100)/100 
+8

請注意,這是不可靠的。例如,用'35.855'來嘗試,最後用'35.85'(不是'35.86')。 – 2013-11-07 07:58:36

+0

noe,這只是一個例子。爲'100' Math.pow插入(10,小數點)'其中'decimalpoint'是你想圍繞你的數字的浮點數的位數 – InsOp 2017-05-16 10:03:36

6
function roundup(num,dec){ 
    dec= dec || 0; 
    var s=String(num); 
    if(num%1)s= s.replace(/5$/, '6'); 
    return Number((+s).toFixed(dec)); 
} 

var n= 35.855 
roundup(n,2) 

/*返回值:(數字) 35.86 */

+2

用'35.855'試一下。 – 2013-11-07 07:59:38

+0

這是我看到的唯一可預測的解決方案。 – 2013-11-21 15:18:46

+0

唯一的問題是,如果其中一個小數位數是5,並且要舍入到的小數位數高於該位置的5位數,則它不起作用。綜述(70.5,2)。這可以通過將replace語句中的正則表達式改爲s.replace(/(\ d {n})5 /,'$ 16')來輕鬆改善,其中n等於dec paraemter。我們只需要在小數點後面的第n + 1位改變5,當四捨五入到小數點後n,我是對嗎? – Mansiemans 2014-02-11 12:06:32

10

在Chrome中,toFixed()輪:

859.385 ==> 859.38 
859.386 ==> 859.39 

當我看着the ECMAScript 5th edition specification for .toFixed()(部分15.7.4.5),我不認爲它明確地描述四捨五入儘管它描述了一些這可能是Chrome已經實施的東西。

在我看來,如果你想用明確的舍入控制它,那麼你或許應該使用的再三建議的解決辦法:

var roundedNum = (Math.round(num * 100)/100).toFixed(2); 

這將保證您獲得可預測的舍入像你用至。

工作演示在這裏:http://jsfiddle.net/jfriend00/kvpgE/

+6

它通常會**保證你得到可預測的舍入。 但是,正如所提到的[在這個答案](JavaScript)處理小數的方式不能真正被信任。 只需在Chrome控制檯中嘗試35.855 * 100 ... 我知道,我也很震驚!這將意味着 '(Math.round(35.855 * 100)/ 100).toFixed(2)== 35.85' 而不是35.86。 看到其他答案的提示... – mattbilson 2013-08-08 15:33:08

0

這可能幫助

tofix2Decimals=function(float){ 
     if(parseInt(float)==float)return float.toFixed(2); 
     $decimals=/\.(\d+)/.exec(float)[1].length; 
     $decimals=$decimals>=2?$decimals+1:3; 
     float+=Math.pow(10,-$decimals); 
     return float.toFixed(2); 
    } 
+4

*解釋*可能有幫助。 – 2013-11-07 08:01:59

1

我偶然發現了這個奇怪,爲什麼Number.toFixed是出現異常行爲。我發現本地函數是不可靠的,這是不幸的。出於好奇,回頭看看答案,我發現其中大多數*的行爲與T.J.的35.855號碼不符。克羅德慷慨地評論每一個人。

也許這會回答你的問題。

function toFixed(n,precision) { 
    var match=RegExp("(\\d+\\.\\d{1,"+precision+"})(\\d)?").exec(n); 
    if(match===null||match[2]===undefined) { 
     return n.toFixed(precision); 
     } 
    if(match[2]>=5) { 
     return (Number(match[1])+Math.pow(10,-precision)).toFixed(precision); 
     } 
    return match[1]; 
    } 

正則表達式將您的數目成字符串,如toFixed(35.855,2)的數組:["35.855", "35.85", "5"]。如果最後一個數字(精度截止後)爲>=5,則將Math.pow(10, -precision)添加到修整數字。如果您以2位小數截止,則將添加.01.002等於3,依此類推。

我不知道這是否萬無一失,因爲它仍然可以執行浮點數的小數運算,這可能是不可預測的。我可以說它輪到35.855高達35.86

0

這是由於JavaScript的浮點表示。

試試這個:

Number.prototype.round = function(digits) { 
    digits = Math.floor(digits); 
    if (isNaN(digits) || digits === 0) { 
     return Math.round(this); 
    } 
    if (digits < 0 || digits > 16) { 
     throw 'RangeError: Number.round() digits argument must be between 0 and 16'; 
    } 
    var multiplicator = Math.pow(10, digits); 
    return Math.round(this * multiplicator)/multiplicator; 
} 

Number.prototype.fixed = function(digits) { 
    digits = Math.floor(digits); 
    if (isNaN(digits) || digits === 0) { 
     return Math.round(this).toString(); 
    } 
    var parts = this.round(digits).toString().split('.'); 
    var fraction = parts.length === 1 ? '' : parts[1]; 
    if (digits > fraction.length) { 
     fraction += new Array(digits - fraction.length + 1).join('0'); 
    } 
    return parts[0] + '.' + fraction; 
} 

用法:

var n = 859.385; 
console.log(n.round(2)); // 859.39 
console.log(n.fixed(2)); // 859.39 
console.log(n.round(4)); // 859.385 
console.log(n.fixed(4)); // 859.3850 
+1

var n = 1.005; console.log(n.round(2))'返回1不是1.01 – 2014-12-05 11:29:40

7

另一個好數量與35.855嘗試一起爲1.005

我不認爲羅伯特Messerle的解決方案處理1.005

這裏舍入十進制的例子https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round將數字轉換爲exponen tial表示法,似乎得到更好的結果。

我創建了一個小提琴這裏http://jsfiddle.net/cCX5y/2/該演示上面的人,羅伯特Messerle例子(稱爲toFixedB)和Mozilla的文檔中的一個(稱爲toFixed10)。

我還沒有找到一個數字,toFixed10錯了。其他人可以嗎?

+0

好的小提琴和鏈接。我添加了user2823670的一行:http://jsfiddle.net/cCX5y/3/ – Slashback 2014-06-18 19:09:38

+0

看起來像[這個答案](http://stackoverflow.com/a/5535472/573634)也可以工作,並不涉及所有額外的代碼。 – Johannes 2016-03-29 17:06:01

+0

所有這些都是不精確的,'toFixed10(89.684449,2)'和其他應該是'89.69',但是是'89.68'。 – mrts 2018-01-01 11:05:44

26

我還沒有找到一個數字,toFixed10錯了。其他人可以嗎?

感謝blghis answer它向我指出Mozilla的toFixed10()方法。

使用,我想出了這樣一個短襯,這的確涵蓋了這裏提到的所有的情況下...

function toFixed(num, precision) { 
    return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision); 
} 
+0

我喜歡它!添加您的單行文本到blg的小提琴:http://jsfiddle.net/cCX5y/3/ – Slashback 2014-06-18 19:10:28

+1

什麼/在哪裏toFixed10?請添加一個鏈接? – ledlogic 2015-03-13 01:20:01

+4

編號0.0000001或更少結果NaN – Greenlandi 2015-07-28 06:33:12

1

我今天遇到了同樣的問題,而在其他的答案,甚至試圖建議,我發現,我仍然沒有收到我預期的結果。最後,因爲我在運行時使用AngularJS來處理當前的項目,我想我會檢查AngularJS是否已經解決了同樣的問題,事實上他們已經解決了。下面是他們所使用的解決方案,它完美的作品對我來說:

function toFixed(number, fractionSize) { 
    return +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize); 
} 

這裏找到:AngularJS filters.js source

+0

這是相同的[這個答案](http://stackoverflow.com/a/23560569/1532548)除了AngularJS沒有尾隨的'.toFixed()' – 2015-08-26 11:40:02

8

我將此作爲最佳舍入函數用於所有財務數據。你可以在所有有問題的數字上測試它。 Javascript允許某種精度,所以我用它來使得幾乎每個數字都按預期舍入。

function roundTo(n, digits) { 
     if (digits === undefined) { 
      digits = 0; 
     } 

     var multiplicator = Math.pow(10, digits); 
     n = parseFloat((n * multiplicator).toFixed(11)); 
     return Math.round(n)/multiplicator; 
    } 
+0

不,這仍然不準確,'roundTo(89.684449,2)'應該是'89.69',但是是'89.68'。 – mrts 2018-01-01 10:59:29

2

由於JavaScript中toFixed功能,浮點數5不屬於一個整數的上半部分,給定的數字四捨五入,如果你有這樣的數字:

859.385.toFixed(2) // results in 859.38

的事實,你可能會追加尾隨浮點數(不爲零)的問題喜歡這裏:

859.3851.toFixed(2) // results in 859.39

因此,開發人員往往會添加像0.00000000001這樣的數字,以便適當舍入並且不會意外更改數字的值。

於是我想出了這取決於你有多少個數字要固定你的浮點數,它增加了這樣一些功能:

// both parameters can be string or number 
    function toFixed(number, decimals) { 
     var x = Math.pow(10, Number(decimals) + 1); 
     return (Number(number) + (1/x)).toFixed(decimals) 
    } 
    toFixed(859.385, 2) //results in 859.39 
+2

最佳答案我可以找到!易於閱讀的代碼,甚至可以處理雙舍入! – Codler 2018-02-23 15:36:32

+0

'toFixed(859.3844,2)'給出'859.39',但應該是'859.38' – 2018-03-06 16:32:29

1

如果你希望得到一個數字作爲輸出 ,然後在其他答案中考慮Math.round()技術。

但是,如果你想獲得一個字符串作爲輸出,呈現給人類,則往往n.toLocaleString()n.toFixed()更有幫助。

爲什麼?因爲它也會將逗號或句點添加到人們用來閱讀的大數字的頭部。例如:

var n = 1859.385 

n.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}) 

// Produces 1,859.39 in USA (locale en-US) 
// Produces 1 859,39 in France (locale fr-FR) 
// Produces 1.859,39 in Germany (locale de-DE) 

該規範指出,通過undefined作爲第一個參數時,用戶自己的區域將被使用(如由操作系統指定)。不幸的是,正如鏈接文檔所示,Mozilla在這種情況下使用en-US語言環境,但它可能會在未來符合規範。

0

歡樂twindle在這裏的答案應該是最好的答案,而不是那麼多的黑客周圍。

x = 1859.385; 
    x = x.toFixed(2); 
    alert(x); 

給出了一個錯誤的取整,即1859.38代替1859.39

x = 1859.385; 
x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); 
alert(x); 

給出了正確的四捨五入1,859.39

唯一的問題是返回的結果是千個逗號分隔符等字符串不能用於計算。使用正則表達式我從堆棧溢出刪除逗號,最終結果是

x = 1859.385; 
x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}); 
x=x.replace(/\,/g,''); 
alert(x); 

現在返回1859.39,可用於計算。 正則表達式之前的值即1,859.39可用於html顯示,而未格式化的值1859.39可用於計算。