javascript - 用适当的替换覆盖 toFixed() 以修复浮点错误 javascript

标签 javascript floating-point precision tofixed

这是我尝试修复 JavaScript toFixed() 函数...

任何意见、想法、对可能错误的更正都非常感谢!

  • 修复浮点误差(例如 (35.355).toFixed(2) = 35.36,不是 35.35)
  • 没有额外的大型库
  • 功能全面(人类可读)
  • 模仿固定/即输出完全相同(尽管对浮点不正确或过程进行了修正)

这是我的尝试 -> 下面的演示(请参阅控制台日志)

enter image description here

Number.prototype.toFixed = function(fractionDigits) {
    var digits = parseInt(fractionDigits) || 0;
    var num = Number(this);
    if( isNaN(num) ) {
        return 'NaN';
    }
    
    var sign = num < 0 ? -1 : 1;
    if (sign < 0) { num = -num; }
    digits = Math.pow(10, digits);
    num *= digits;
    num = Math.round( Math.round(num * Math.pow(10,12)) / Math.pow(10,12) );
    var finalNumber = sign * num / digits;

    // add 0 after last decimal number (not 0) for as many as requested (fractionDigits)
    // in else case, check if requested digits exceed actual, then add 0 (avoid 10.1 for toFixed(2))

    if(fractionDigits > 0 && finalNumber.toString().indexOf('.') == -1){
        // check that .00 is present
        finalNumber = finalNumber.toString() + '.' + '0'.repeat(fractionDigits);
    } else if(fractionDigits > finalNumber.toString().split('.')[1]?.length){
        finalNumber = finalNumber.toString() + '0'.repeat((fractionDigits - finalNumber.toString().split('.')[1]?.length));
    }
    
    return finalNumber.toString(); // tofixed returns as string always, do the same
}

console.log('(35.355).toFixed(2)', (35.355).toFixed(2));
console.log('(35.1).toFixed(2)', (35.1).toFixed(2));
console.log('(35).toFixed(2)', (35).toFixed(2));

Number.prototype.toFixed = function(fractionDigits) {
//function toFixed(numberInput, fractionDigits){
    var digits = parseInt(fractionDigits) || 0;
    var num = Number(this);
    if( isNaN(num) ) {
        return 'NaN';
    }
    
    var sign = num < 0 ? -1 : 1;
    if (sign < 0) { num = -num; }
    digits = Math.pow(10, digits);
    num *= digits;
    num = Math.round( Math.round(num * Math.pow(10,12)) / Math.pow(10,12) );
    var finalNumber = sign * num / digits;

    // add 0 after last decimal number (not 0) for as many as requested (fractionDigits)

    if(fractionDigits > 0 && finalNumber.toString().indexOf('.') == -1){
        // check that .00 is present
        finalNumber = finalNumber.toString() + '.' + '0'.repeat(fractionDigits);
    } else if(fractionDigits > finalNumber.toString().split('.')[1]?.length){
        finalNumber = finalNumber.toString() + '0'.repeat((fractionDigits - finalNumber.toString().split('.')[1]?.length));
    }
    
    return finalNumber.toString(); // tofixed returns as string always, do the same
}

console.log('post-fix | (35.355).toFixed(2)', (35.355).toFixed(2));
console.log('post-fix | (35.1).toFixed(2)', (35.1).toFixed(2));
console.log('post-fix | (35).toFixed(2)', (35).toFixed(2));

最佳答案

如果是我,我可能会采用这种字符串操作方法:

Number.prototype.toFixed = function(fractionDigits) {
  var number = String(this);
  var digits = fractionDigits || 0, length;
  
  if(digits < 0 && digits > 100) 
    throw 'RangeError: toFixed() digits argument must be between 0 and 100';

  var decimal = number.match(/(?<=\.)(\d*)/g);
  var factor = Math.pow(10, digits);
  if (decimal && decimal[0].length >= digits) 
    return String(Math.round(Number(number + '1') * factor) / factor);
  else {
    var length = digits - (decimal ? decimal[0].length : 0);
    var delimiter = number.includes('.') || !length ? '' : '.';
    return String(number) + delimiter + '0'.repeat(length);
  }
}

function test() {
  console.log((-35.555).toFixed(2))
  console.log((-35.35).toFixed(2))
  console.log((-35.9).toFixed(2))
  console.log((-35).toFixed(2))
}

注意:

  • 我认为您不会在 toFixed 中遇到字符串因为它不会被它触发,所以你不需要 isNaN检查一下。
  • 当参数小于 0 或大于 100 时提前捕获。这应该会抛出与原始错误类似的错误。

输出:

output

关于javascript - 用适当的替换覆盖 toFixed() 以修复浮点错误 javascript,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72052086/

相关文章:

c# - Math.Floor(double) 和 Math.Ceiling(double) 的意外行为

c++ - 这种浮子的最大尺寸是多少?

c++ - 机器精度

javascript - 页脚使用 .slideUp 向上滑动但随后向下滑动

Matlab sin(pi) 及其与机器 epsilon 的关系

javascript - 使用 JavaScript 打开 ModalPopupExtender

C# int 存储在 double "=="精度问题

java - 如何将一个非常小的数字和一个非常大的数字相加

javascript - 如何将 super 菜单的Click事件转换为hover

javascript - JSON.parse javascript 中的 JSON 字符串