34

49.90 % 0.10JavaScript で が返されるのはなぜ0.09999999999999581ですか? 0になると予想していました。

4

7 に答える 7

57

JavaScript は浮動小数点演算を使用するため、丸めエラーが発生する可能性があります。

小数点以下 2 桁の正確な結果が必要な場合は、100演算の前に数値を掛けてから、後で再度割ります。

var result = ( 4990 % 10 ) / 100;

必要に応じて丸めます。

于 2010-10-19T08:28:44.253 に答える
20

Javascript の数値は、「IEEE 倍精度」を使用して値を格納しています。すべての 10 進数を正確に格納することはできません。10 進数を 2 進数に変換するときの丸め誤差のため、結果はゼロではありません。

49.90 = 49.89999999999999857891452848...
 0.10 =  0.10000000000000000555111512...

したがって、floor(49.90 / 0.10) は 498 だけで、残りは 0.09999 になります....


金額を格納するために数字を使用しているようです。浮動小数点演算は丸め誤差を伝播および増幅するため、これを行わないでください。代わりに、数値をセント単位で保存します。整数は正確に表すことができ、4990 % 100 を返します。

于 2010-10-19T08:32:10.073 に答える
18

今後の参考のためにここに残しておきますが、フロートを含む剰余をより正確に処理できる便利な関数を次に示します( JS にはモジュロ演算子がないため)。

  function floatSafeRemainder(val, step){
    var valDecCount = (val.toString().split('.')[1] || '').length;
    var stepDecCount = (step.toString().split('.')[1] || '').length;
    var decCount = valDecCount > stepDecCount? valDecCount : stepDecCount;
    var valInt = parseInt(val.toFixed(decCount).replace('.',''));
    var stepInt = parseInt(step.toFixed(decCount).replace('.',''));
    return (valInt % stepInt) / Math.pow(10, decCount);
  }

$(function() {
  
  
  function floatSafeModulus(val, step) {
    var valDecCount = (val.toString().split('.')[1] || '').length;
    var stepDecCount = (step.toString().split('.')[1] || '').length;
    var decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount;
    var valInt = parseInt(val.toFixed(decCount).replace('.', ''));
    var stepInt = parseInt(step.toFixed(decCount).replace('.', ''));
    return (valInt % stepInt) / Math.pow(10, decCount);
  }
  
  
  $("#form").submit(function(e) {
    e.preventDefault();
    var safe = 'Invalid';
    var normal = 'Invalid';
    var var1 = parseFloat($('#var1').val());
    var var2 = parseFloat($('#var2').val());
    if (!isNaN(var1) && !isNaN(var2)) {
      safe = floatSafeModulus(var1, var2);
      normal = var1 % var2
    }
    $('#safeResult').text(safe);
    $('#normalResult').text(normal);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form id="form" novalidate>
  <div>
    <input type="number" id="var1">%
    <input type="number" id="var2">
  </div>
  <div>safe: <span id="safeResult"></span><div>
  <div>normal (%): <span id="normalResult"></span></div>
  <input type="submit" value="try it out">
</form>

于 2015-07-29T21:00:35.147 に答える
1

浮動小数点とその欠点を見てみましょう- のような数値0.1は浮動小数点として正しく保存できないため、常にこのような問題が発生します。数値 *10 または *100 を代わりに整数で計算してください。

于 2010-10-19T08:30:35.310 に答える
0

http://en.wikipedia.org/wiki/Modulo_operation 怒ってはいけません モジュロは整数で使用されます ^^ そのため、浮動小数点値はいくつかのエラーを発生させます。

于 2010-10-19T08:29:44.177 に答える