0

JavaScript で 2 つの実数の中間点 (平均) を計算する必要があります。数値の範囲は大きく異なり、通常は 10000 から 0.0001 の間です。

素朴なアプローチ

(parseFloat(first) + parseFloat(second)) / 2

不要な精度エラーが発生します。つまり、

(1.1 + 0.1) / 2 = 0.6000000000000001

結果に余分な小数点以下のスペースが含まれないようにするにはどうすればよいですか? 入力が 2 つしかないため、結果の小数点以下の桁数は入力よりも最大で 1 つ多い必要があると思います。だから、私は必要です:

 1000 and 3000 to return 2000 (without decimal spaces)
 1234.5678 and 2468.2468 to return 1851.4073
 0.001 and 0.0001 to return 0.00055
 10000 and 0.0001 to return 5000.00005
 0.1 and 1.1 to return 0.6

明確にするために:私は精度エラーとこれが起こる理由についてすべて知っています. 私が必要としているのは簡単な回避策であり、SO に関する以前の解決策を見つけることができませんでした。

4

5 に答える 5

3

関数を使用する必要がありますtoFixed()。コードは次のようになります((1.1 + 0.1) / 2).toFixed(4);。4 は小数点以下の桁数です。

これがサンプルです

var num1 = "123.456";
var num2 = "456.1235";
if (num1.split('.')[1].length > num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num1.split('.')[1].length+1);
else
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length+1);

入力は文字列であることを忘れないでください。そのため、num1num2は文字列です。

更新:これは、目的の結果に対する正しい if ステートメントです。

var num1 = "123.456";
var num2 = "456.1235";
if (num1.split('.').length == 1) {
  if (num2.split('.').length == 1)
    var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(0);
  else
    var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
} else if (num2.split('.').length == 1)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
else if (num1.split('.')[1].length == num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length);
else if (num1.split('.')[1].length > num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num1.split('.')[1].length+1);
else if (num1.split('.')[1].length < num2.split('.')[1].length)
  var x = ((parseFloat(num1) + parseFloat(num2)) / 2).toFixed(num2.split('.')[1].length+1);

編集小数点以下のスペースがない数値をチェックする順序を変更する必要がありました。テストに役立つように作成した jsFiddle を次に示します

于 2013-01-30T16:12:33.833 に答える
2

Javascript の数値には、toFixed(n)小数点以下 n 桁を除くすべてを削除するメソッドがあります。ただし、これは、数値が非常に大きいか小さいかがわからない場合にはあまり役に立ちません。しかし、できることは、最初に対数の Math.floor() を数値の底 10 にして、ドットの前の小数点以下の桁数を取得し、数値を 10^ 桁で割り、toFixed(n)n が最大数である場合に実行することです。の桁数を計算し、それを 10^ 桁で再度乗算します。

于 2013-01-30T16:19:48.593 に答える
1

JavaScript の数値はすべて、 IEEE754で定義されている倍精度浮動小数点数です。これは、基数 10 で定義されたドット位置がないことを意味し、必要な精度が得られない場合が常にあることを意味します。

解決策は次のいずれかです

  • 計算を行うためにjs番号を使用しないでください。このソリューションは重く、通常は役に立ちません。
  • 数値を表示する必要があるときに (そのときだけ) 数値を文字列にフォーマットします。to Fixed または toPrecision を使用できます。

参考資料 :すべてのコンピュータ科学者が浮動小数点演算について知っておくべきこと

于 2013-01-30T16:13:55.480 に答える
1

使用中の数値の「精度」を使用して、戻り値の適切な精度を判断できます。

この例では、任意の数の数値をその引数の最大精度で平均化します。

Math.average= function(){
    var a= arguments, L= a.length, i= 0,
    total= 0, next, prec= [];
    if(L== 1) return +a[0];
    while(i<L){
        next= Number(a[i++]);
        total+= next;
        if(next!== Math.floor(next)){
            prec.push(String(next).split('.')[1].length);
        }
    }
    prec= Math.max.apply(Math, prec)+1;
    return +((total/L).toFixed(prec));
    // returns number after precision adjusted
}

/*

tests:
var n1= ;
Math.average(1.1, .01);
0.555

var n1= 1.0111, n2= .01;
Math.average(1.0111,  .01);
0.51055

var n1= 1.1, n2= .01, n3= 1, n4= 1.025;
Math.average(n1, n2, n3, n4)
0.7838

*/

于 2013-01-30T17:31:29.840 に答える
0

Number.toPrecision(digits)を使用してそれを行うことができます。

于 2013-01-30T16:26:00.357 に答える