2016-01-12 3 views
0

Каждый программист javascript знает, что javascript Math.round() не приводит к правильному округлению десятичных чисел во многих случаях из-за ошибочной арифметики с плавающей запятой.Округление десятичных чисел в Javascript

Наиболее решения говорят использовать простое расширение прототипа:

Number.prototype.round = function (decimalPlaces) { 
    decimalPlaces = decimalPlaces || 0; 
    var power = Math.pow(10, decimalPlaces) 

    if (this > 0) { 
     return Math.round(this * power)/power; 
    } else { 
     return -(Math.round(Math.abs(this) * power)/power); 
    } 
}; 

Но это терпит неудачу на (1.005).round(2), который возвращает 1 вместо ожидаемого 1.01.

Как правильно округлить десятичные числа в javascript? См. Решение ниже (с модульными испытаниями).

+0

Лично я лучше всего работать с целыми числами и делиться только на 100 или что угодно для показа;) –

ответ

0

Правильный номер расширения прототипа для округления десятичных чисел:

Number.prototype.round = function (decimalPlaces) { 
    decimalPlaces = decimalPlaces || 0; 

    var sign = (this < 0) ? -1 : 1, 
     exp = -decimalPlaces, 
     value; 

    // Shift 
    value = Math.abs(this).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))) * sign; 
}; 

Это расширение Твик из decimalAdjust(), упоминается the Mozilla Developer Network Documentation for Math.round():

QUnit испытания для этого решения:

test("Number.prototype.round", function() { 
    var value; 

    value = 0; 
    equal(value.round(0), 0, "Value: 0, decimals: 0, expected result: 0"); 

    value = 33.12; 
    equal(value.round(1), 33.1, "Value: 33.12, decimals: 1, expected result: 33.1"); 

    value = 33.15; 
    equal(value.round(1), 33.2, "Value: 33.15, decimals: 1, expected result: 33.2"); 

    value = 33.123; 
    equal(value.round(2), 33.12, "Value: 33.123, decimals: 2, expected result: 33.12"); 

    value = 1000033.125; 
    equal(value.round(2), 1000033.13, "Value: 1000033.125, decimals: 2, expected result: 1000033.13"); 

    value = 17.6949; 
    equal(value.round(2), 17.69, "Value: 17.6949, decimals: 2, expected result: 17.69"); 

    value = 33.1234; 
    equal(value.round(3), 33.123, "Value: 33.1234, decimals: 3, expected result: 33.123"); 

    value = 33.12359; 
    equal(value.round(3), 33.124, "Value: 33.12359, decimals: 3, expected result: 33.124"); 

    value = 33.12343; 
    equal(value.round(4), 33.1234, "Value: 33.12343, decimals: 4, expected result: 33.1234"); 

    value = 33.12346; 
    equal(value.round(4), 33.1235, "Value: 33.12346, decimals: 4, expected result: 33.1235"); 

    value = 33.123456789; 
    equal(value.round(5), 33.12346, "Value: 33.123456789, decimals: 5, expected result: 33.12346"); 

    value = 33.123456789; 
    equal(value.round(8), 33.12345679, "Value: 33.123456789, decimals: 8, expected result: 33.12345679"); 

    value = -123456.123456789; 
    equal(value.round(8), -123456.12345679, "Value: -123456.123456789, decimals: 8, expected result: -123456.12345679"); 

    value = -110.385; 
    equal(value.round(2), -110.39, "Value: -110.385, decimals: 2, expected result: -110.39"); 
}); 
+0

You shoul dn't расширять собственные объекты в JavaScript -> http://stackoverflow.com/questions/14034180/why-is-extending-native-objects-a-bad-practice –

+0

Ну, это расширение прототипа можно легко переписать на стандартную функцию , – petriq

+0

Я знаю. Так что, может быть, вам следует ;-) –

Смежные вопросы