假设我有一个值15.7784514,我想把它显示为15.77,没有舍入。

var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));

结果:

15.8
15.78
15.778
15.7784514000 

如何显示15.77?


当前回答

如果你想精确地截断为2位精度,你可以使用一个简单的逻辑:

function myFunction(number) {
  var roundedNumber = number.toFixed(2);
  if (roundedNumber > number)
  {
      roundedNumber = roundedNumber - 0.01;
  }
  return roundedNumber;
}

其他回答

function toFixed(num, fixed) {
    fixed = fixed || 0;
    var front = Math.floor(num);
    var back = 0;
    for (var i = 1; i <= fixed; i++) {
        var value = Math.floor(num * Math.pow(10, i)) % 10;
        back += value / Math.pow(10, i);
    }
    return front + back;
}

我的解决方案在typescript(可以很容易地移植到JS):

/**
 * Returns the price with correct precision as a string
 *
 * @param   price The price in decimal to be formatted.
 * @param   decimalPlaces The number of decimal places to use
 * @return  string The price in Decimal formatting.
 */
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
  price: number,
  decimalPlaces: number = 2,
): string => {
  const priceString: string = price.toString();
  const pointIndex: number = priceString.indexOf('.');

  // Return the integer part if decimalPlaces is 0
  if (decimalPlaces === 0) {
    return priceString.substr(0, pointIndex);
  }

  // Return value with 0s appended after decimal if the price is an integer
  if (pointIndex === -1) {
    const padZeroString: string = '0'.repeat(decimalPlaces);

    return `${priceString}.${padZeroString}`;
  }

  // If numbers after decimal are less than decimalPlaces, append with 0s
  const padZeroLen: number = priceString.length - pointIndex - 1;
  if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
    const padZeroString: string = '0'.repeat(padZeroLen);

    return `${priceString}${padZeroString}`;
  }

  return priceString.substr(0, pointIndex + decimalPlaces + 1);
};

测试用例:

  expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
  expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
  expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
  expect(filters.toDecimalOdds(8.2)).toBe('8.20');

任何改善吗?

这些解决方案确实有效,但对我来说似乎没有必要这么复杂。我个人喜欢用模运算符来得到除法运算的余数,然后去掉余数。假设num = 15.7784514:

num-=num%.01;

这相当于说num = num - (num % .01)。

我选择写这个来手动删除剩余的字符串,这样我就不必处理数字带来的数学问题:

num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number

这将得到“15.77”,其中num = 15.7784514;

2016年11月5日更新

新的答案,总是准确的

function toFixed(num, fixed) {
    var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
    return num.toString().match(re)[0];
}

由于javascript中的浮点数学总是有边缘情况,所以之前的解决方案在大多数情况下都是准确的,这是不够的。 有一些解决方案,如num.toPrecision, BigDecimal.js和accounting.js。 然而,我相信仅仅解析字符串是最简单的,而且总是准确的。

基于@Gumbo接受的答案的良好编写的正则表达式的更新,这个新的toFixed函数将始终按预期工作。


老答案,并不总是准确的。

固定功能:

function toFixed(num, fixed) {
    fixed = fixed || 0;
    fixed = Math.pow(10, fixed);
    return Math.floor(num * fixed) / fixed;
}