web-dev-qa-db-ja.com

Javascriptで乗算する方法は?小数の問題

私はJavascriptで次のコードを持っています:

var m1 = 2232.00;
var percent = (10/100);
var total = percent*m1;
alert(total);

問題は、変数「total」から「223.20000000000002」が得られ、「223.2」になるはずであるということです。正しい値を取得するにはどうすればよいですか?

24
gustavomanolo

。toFixed()が最善の解決策です。ドットの後の2桁のみを保持します。

経験1:

var value = 3.666;
value.toFixed(2); //Output : 3.67

経験2:

var value = 3.0000;
value.toFixed(2); //Output : 3.00
20
Malik Khalil

正確な値を取得することはできません。これは、浮動小数点数の基本的な問題です。

toFixedを使用して、固定数の10進数を強制できます。

_alert(total.toFixed(2));
_

ただし、これにより末尾のゼロが残ることに注意してください。 .replace(/0+$/,'');で削除できます

7

Dimitry のおかげで、次のページを使用して答えを見つけました。

JavaScriptの浮動小数点チートシート

私は操作の正確な値が必要であり、お金の操作に関連しているため、次のクラスを使用することにしました:

4
gustavomanolo

この番号を表示しようとしている場合は、 toFixed(1) を使用して文字列に変換できます。これを行う場合、文字列に別の数値を掛けることはできないため、型を追跡してください。

別の計算で使用する場合は、小数点以下1桁に切り捨てることができます。

Math.round( total * 10 ) / 10

ただし、さまざまな人々が指摘しているように、不正確な値は浮動小数点数と同じです。

より良い情報については、コメントにリンクされている質問を参照してください。

4
WildCrustacean

これは、JavaScriptにDecimal型を提供する decimal.js と呼ばれる外部ライブラリでうまく実行できます。 npmのNodeでも使用できます。以下は、decimal.jsを使用してgustavomanoloから元の例を複製する例です。

// Decimal type provided by decimal.js (http://mikemcl.github.io/decimal.js/)
var m1 = new Decimal( 2232.00 );
var percent = new Decimal( 10/100 );
var total = m1.mul(percent);
console.log( 'Total:', total );
<script src="https://cdnjs.cloudflare.com/ajax/libs/decimal.js/7.2.3/decimal.min.js"></script>
3
Kevin Leary

演算子「*」と「/」は常に完全に機能するわけではありません。次に例を示します。

32.09 * 100 = 3209.0000000000005
100 / (1 / 32.09) = 3209.0000000000005

解決策:

簡単な解決策の1つは、.toFixed(2)を使用することです(「2」は希望する10進数の桁数です)。ただし、これが文字列を返すことを考慮する必要があり、値を丸めます。

45.6789.toFixed(2) —> "45.68" as String

最も完全な他のオプションは、.toLocaleStringを使用することです。これは、番号を目的の国コードに適切に変換します。ペアのパラメーターを設定して、小数値を常に2に修正できます。これにより、ストリングも返されます。

(654.3453).toLocaleString(
  'en-US',
  {minimumFractionDigits: 2, maximumFractionDigits: 2},
) —> "654.35" as String

数値として必要な場合は、Number(...)にラップできます。

Number((654.3453).toLocaleString(
  'en-US',
  {minimumFractionDigits: 2, maximumFractionDigits: 2},
)) —> 654.35 as Number

10進数を使用しない場合は、このメソッドのいずれかを使用して、結果に小数がないことを確認してください。

Math.trunc(32.09); —> 32 as Number  
(32.09).toFixed(0); —> “32” as String
32.09 | 0; —> 32 as Number
2
DrWaky

total.toFixed(2)が役立つ場合があります。ただし、total変数は文字列に型キャストされることに注意してください。

2
srijan

浮動小数点数の乗算の解決策は次のとおりです。それは非常に簡単ですが、私のために動作します。この関数を使用すると、数字の小数点以下の桁数がわかります。

function decimalPlaces(num) {
    var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
    if (!match) { return 0; }
    return Math.max(
        0,
        // Number of digits right of decimal point.
        (match[1] ? match[1].length : 0)
        // Adjust for scientific notation.
        - (match[2] ? +match[2] : 0));
}

そして、あなたの最終的な答え「合計」のためにあなたがします

total = total.toFixed(decimalPlaces(a)+decimalPlaces(b));

ここで、a、bはあなたの番号です

2
PetrosM

ちょうど試して

var x = 0.07;
console.log((x+1)*100 - 100);

ここで、xの値を他の値に置き換えます;-)

1
rubens21

私は次の解決策になりました:

function decimalmultiply(a, b) {
    return parseFloat((a * b).toFixed(12));
}

10.50*30.45=319.72499999999997
decimalmultiply(10.50,30.45)=319.725

このメソッドは、stringではなくnumberを返します。有効な小数部(最大12)を切り捨てることはありません。

1
Erik123

できる

var total = +(percent*m1).toPrecision(15);

223.2 === total;          // true
223.2 === 0.1*2232.00;    // false
0
MikeM

非常に簡単な解決策を見つけました。 _*_演算子は10進数になると少し壊れますが、_/_演算子はそうではありません。 a•b = a /(1/b)なので、乗算は簡単に除算に変換できます。

_function times(a, b) { return a/(1/b) }
_

_percent * m1_をtimes(percent, m1)に置き換えるだけです。

更新:常に動作しません。

0
Stefan Octavian

Angularを使用している場合、このためのコンポーネントを作成しました。

バウアーでインストール

bower install angular-floating-point --save

使用法

var pretty = floatingPoint.makePretty(6.1*6);

こちらがデモです-> https://mattspaulding.github.io/angular-floating-point
ソースはこちら-> https://github.com/mattspaulding/angular-floating-point

以下のスニペットで自分で試してください。

 angular.module('myApp', ['floatingPoint'])
  .controller('myCtrl', function ($scope, floatingPoint) {

      $scope.calculate = function () {
        $scope.result =$scope.num0*$scope.num1;
        $scope.prettyResult=floatingPoint.makePretty($scope.result)
      }

      $scope.num0=6.1;
      $scope.num1=6;
      $scope.calculate();

    });
 
<html>

<head>
  <title>My Angular App</title>
  <script src='//code.jquery.com/jquery-latest.min.js'></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
  <!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">

<!-- Optional theme -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">

<!-- Latest compiled and minified JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="https://rawgit.com/mattspaulding/angular-floating-point/master/dist/angular-floating-point.min.js"></script>
</head>

<body ng-app="myApp" ng-controller="myCtrl">
    <div class="row" style="padding-top: 10px;text-align:center">
      <label>(try me) ==> </label>
      <input ng-model="num0" ng-change="calculate()" style="width:100px; height:30px">
      X
      <input ng-model="num1" ng-change="calculate()" style="width:100px; height:30px">
    </div>
    <div class="row" style="padding-top: 50px;">
      <div class="col-xs-6">
        <label style="float: right;">Ugly calculation:</label>
      </div>
      <div class="col-xs-6">
        <label style="float: left;">{{result}}</label>
      </div>
    </div>
    <div class="row" style="padding-top: 20px;">
      <div class="col-xs-6">
        <label style="float: right;"><span style="color:blue">Angular Floating Point</span> calculation:</label>
      </div>
      <div class="col-xs-6">
        <label style="float: left;">{{prettyResult}}</label>
      </div>
    </div>

</body>
0
Matt