Javascript Math.floor特定数字范围之间的问题

时间:2015-05-14 01:35:09

标签: javascript jquery knockout.js floating-point-precision

我在下面的场景中遇到了javascript的Math.floor函数的问题:

1)来自8192和10484的值,

    if I type 8192.8  -> The Math.floor converts it into 8192.79

    if I type 8192.88  -> The Math.floor converts it into 8192.87

    if I type 8192.3  -> The Math.floor converts it into 8192.29

奇怪的是,除了上面给出的范围外,该功能运行正常。

HTML:
<div data-bind="text: popIncrease"></div>
<input type="text" data-bind="value: userInput,  valueUpdate: 'afterkeydown'" />

Javascript:

var ViewModel = function () {
var _self = this;
_self.userInput = ko.observable();
_self.popIncrease = ko.computed(function () {

        return parseFloat((Math.floor(_self.userInput() * 100) / 100)).toFixed(2);
});
};

ko.applyBindings(new ViewModel());

的jsfiddle:https://jsfiddle.net/91z5bdy4/1/

当我用1000改变100时它解决了错误,但我不明白为什么这发生在第一个地方?

4 个答案:

答案 0 :(得分:1)

您可以切换到:

return parseFloat(_self.userInput()).toFixed(2);

jsFiddle的工作版本:https://jsfiddle.net/jfriend00/5rLL04Lk/

或者,如果你想解决.toFixed()的某些特性,你可以使用它:

return (Math.round(_self.userInput() * 100) / 100).toFixed(2);

工作jsFiddle:https://jsfiddle.net/jfriend00/xx2aj2L0/

此解决方案通过了所有三个测试用例。

答案 1 :(得分:1)

导致问题的不是Math.floor(),而是浮点运算的不精确性。将8192.8乘以100后,您会获得819279.9999999999

也许您应该将其作为字符串进行操作:

function floorString(str) {
    var pos = str.indexOf('.');
    return (pos >= 0) ? ((str + '00').slice(0, pos + 3)) : (str + '.00');
}

jsfiddle

答案 2 :(得分:0)

您的发言/解析顺序似乎不合适。

尝试:

return Math.floor(parseFloat(_self.userInput())).toFixed(2);

虽然知道1.999999999999999999999999999999使用上述2.00给出;这是因为浮点数不能精确地表示所有值。

答案 3 :(得分:0)

另一个没有使用Math功能(没有格式化的2行)

function floorString(str) {
    var matches = str.match(/([\d]+(\.[\d]{0,2}))/);
    return matches === null || matches[2].length === 1 ?
            (str + ".00").replace("..", ".") :
            matches[2].length < 3 ?
                matches[0] + "00".substr(3 - matches[2].length) :
                matches[0];
}