網站搜尋

四捨五入 - 在 JavaScript 中將數字格式化為正好兩位小數


我有這行程式碼會將我的數字四捨五入到小數點後兩位。但我得到的數字像這樣:10.8、2.4 等等。這些不是我心目中的兩位小數,那我該如何改進以下程式碼呢?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

我想要像 10.80、2.40 這樣的數字。使用 jQuery 對我來說沒問題。

答案#1

要使用固定小數點表示法格式化數字,你可以簡單地使用 toFixed 方法:

(10.8).toFixed(2); // "10.80"

var num = 2.4;
alert(num.toFixed(2)); // "2.40"

請注意,toFixed() 會回傳一個字串。

重要:請注意,toFixed 在 90% 的情況下不會進行四捨五入,它會返回四捨五入的值,但在許多情況下,它不起作用。

例如:

2.005.toFixed(2) === "2.00"

更新:

如今,你可以使用 Intl.NumberFormat 建構函式。它是 ECMAScript 國際化 API 規範(ECMA402)的一部分。它有相當好的瀏覽器支援,包括 IE11,並且在 Node.js 中也完全支援。

const formatter = new Intl.NumberFormat('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});

console.log(formatter.format(2.005)); // "2.01"
console.log(formatter.format(1.345)); // "1.35"

你也可以使用 toLocaleString 方法,它內部將使用 Intl API:

const format = (num, decimals) => num.toLocaleString('en-US', {
   minimumFractionDigits: 2,      
   maximumFractionDigits: 2,
});


console.log(format(2.005)); // "2.01"
console.log(format(1.345)); // "1.35"

此 API 還為您提供了多種格式化選項,例如千位分隔符、貨幣符號等。

答案#2

這是一個舊話題,但仍然是 Google 搜尋結果中的熱門,且提供的解決方案都存在相同的浮點數小數問題。以下是我使用的(非常通用的)函數,感謝 MDN:

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

如我們所見,我們沒有遇到這些問題:

round(1.275, 2);   // Returns 1.28
round(1.27499, 2); // Returns 1.27

這種泛型性還提供了一些很酷的功能:

round(1234.5678, -2);   // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45");        // Returns 123

現在,要回答發帖者的問題,必須輸入:

round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2);    // Returns "10.80"

或者,對於一個更簡潔、較不通用的函數:

function round2Fixed(value) {
  value = +value;

  if (isNaN(value))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));

  // Shift back
  value = value.toString().split('e');
  return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}

你可以用以下方式呼叫它:

round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8);    // Returns "10.80"

各種範例和測試(感謝 @t-j-crowder!):

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}
function naive(value, exp) {
  if (!exp) {
    return Math.round(value);
  }
  var pow = Math.pow(10, exp);
  return Math.round(value * pow) / pow;
}
function test(val, places) {
  subtest(val, places);
  val = typeof val === "string" ? "-" + val : -val;
  subtest(val, places);
}
function subtest(val, places) {
  var placesOrZero = places || 0;
  var naiveResult = naive(val, places);
  var roundResult = round(val, places);
  if (placesOrZero >= 0) {
    naiveResult = naiveResult.toFixed(placesOrZero);
    roundResult = roundResult.toFixed(placesOrZero);
  } else {
    naiveResult = naiveResult.toString();
    roundResult = roundResult.toString();
  }
  $("<tr>")
    .append($("<td>").text(JSON.stringify(val)))
    .append($("<td>").text(placesOrZero))
    .append($("<td>").text(naiveResult))
    .append($("<td>").text(roundResult))
    .appendTo("#results");
}
test(0.565, 2);
test(0.575, 2);
test(0.585, 2);
test(1.275, 2);
test(1.27499, 2);
test(1234.5678, -2);
test(1.2345678e+2, 2);
test("123.45");
test(10.8034, 2);
test(10.8, 2);
test(1.005, 2);
test(1.0005, 2);
table {
  border-collapse: collapse;
}
table, td, th {
  border: 1px solid #ddd;
}
td, th {
  padding: 4px;
}
th {
  font-weight: normal;
  font-family: sans-serif;
}
td {
  font-family: monospace;
}
<table>
  <thead>
    <tr>
      <th>Input</th>
      <th>Places</th>
      <th>Naive</th>
      <th>Thorough</th>
    </tr>
  </thead>
  <tbody id="results">
  </tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

答案#3

我通常會將這個加入我的個人資料庫,經過一些建議並使用 @TIMINeutron 的解決方案,然後將其調整以適應小數長度後,這個最適合:

function precise_round(num, decimals) {
   var t = Math.pow(10, decimals);   
   return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}

將適用於所報告的例外情況。

答案#4

快速且簡單

parseFloat(number.toFixed(2))

例子

let number = 2.55435930

let roundedString = number.toFixed(2)    // "2.55"

let twoDecimalsNumber = parseFloat(roundedString)    // 2.55

let directly = parseFloat(number.toFixed(2))    // 2.55

答案#5

確保你得到一個帶有兩位小數的數字的其中一種方法:

(Math.round(num*100)/100).toFixed(2)

如果這會導致四捨五入錯誤,你可以使用以下方法,就像 James 在他的評論中解釋的那樣:

(Math.round((num * 1000)/10)/100).toFixed(2)

答案#6

我不知道為什麼我不能對之前的回答添加評論(也許我真的看不見,我不知道),但是我想出了一個使用 @Miguel 的回答的解決方案:

function precise_round(num,decimals) {
   return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}

以及它的兩條評論(來自 @bighostkim 和 @Imre):

  • precise_round(1.275,2) 無法返回 1.28 的問題
  • 在使用 precise_round(6,2) 時出現問題,沒有返回 6.00(如他所希望的)。

我的最終方案如下:

function precise_round(num,decimals) {
    var sign = num >= 0 ? 1 : -1;
    return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}

如你所見,我必須加入一點“修正”(它實際上不是修正,但由於 Math.round 是有損的 —— 你可以在 jsfiddle.net 上檢查 —— 這是我唯一知道的“修復”方法)。它會在已經補零的數字上加上 0.001,所以它相當於在小數點右側添加了一個 1,後面跟著三個 0。所以使用起來應該是安全的。

之後我加上了 .toFixed(decimal),以始終以正確的格式輸出數字(具有正確的小數位數)。

大概就是這樣。好好使用它吧 ;)

編輯:為負數的「更正」新增了功能。

答案#7

toFixed(n) 提供小數點後 n 位長度;toPrecision(x) 提供總長度為 x。

使用以下方法

// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
    // It will round to the tenths place
    num = 500.2349;
    result = num.toPrecision(4); // result will equal 500.2

如果你想要這個數字被固定,請使用

result = num.toFixed(2);