3

JavaScript を使用して、浮動小数点数が別の浮動小数点数の倍数であるかどうかを判断する必要があります。

浮動小数点数に関する他の質問をいくつか読みましたが、モジュロ演算子 (%) では正しく機能しないことがわかりました。また、10/100/1000 などを掛けることで浮動小数点数を整数に変換できることも読みましたが、これはすべての場合に正しく機能するとは限りません。

例:

var A = 25.13;
var B = .0001;

var Value = A*1e5;
var Step  = B*1e5;

// Is Value a multiple of Step?
if(0 === (Value % Step)) {
// Do something
}

この場合、Value は Step の倍数であり、正しく機能します。しかし、どうですか:

var A = 2.2;
var B = .0001;

有効な倍数である必要がありますが、代わりに次のようになります。

220000.00000000003 % 10 = 2.9103830456733704e-11

小数点第 11 位に誤った 3 があります。次のようにして、丸めの問題を修正できると思いtoFixed()ました。

var Value = (A*1e5).toFixed(10);
var Step  = (B*1e5).toFixed(10);

しかし、そうする場合:

var A = 45436212356482;
var B = .0001;

あなたは得る:

4543621235648200192.0000000000 % 10.0000000000=2

有効な倍数ですが、そうではないと考えています。

と:

var A = 45436212546522156.45621565421;
var B = .0001;

これは有効な倍数ではありませんが、次のように考えられます。

4.543621254652216e+21 % 10.0000000000=0

ある浮動小数点が別の浮動小数点の倍数かどうかを判断する巧妙なトリックはありますか? それともこれは不可能ですか?

アップデート:

目標は、ユーザーが入力する数値 (整数または小数) を特定の増分に制限することです。

  • Increment が 1 の場合、ユーザーは 1、2、3、4 などを入力できます。
  • Increment が .5 の場合、ユーザーは .5、1、1.5、2、2.5 などと入力できます。
  • Increment が .0002 の場合、ユーザーは 1,1.001,1.0004,1.0006 を入力できますが、1.0001 は入力できません。

論理的な観点からは、特定の値が特定のインクリメントの有効な倍数である場合とそうでない場合があります。

4

7 に答える 7

4

4543621235648200192 などの最後の 2 つの例を考えると、.0001 の整数倍の数値を受け入れ、そうでない数値を拒否し、.0001 を使用せずに浮動小数点を含む変数を使用してこれを行いたいようです。ポイント値に最も近い.0001。

一般的に、それは不可能です。他の何かを渡したときに、.0001 が意図されたものであることをアルゴリズムが「知る」方法はありません。

問題をさらに制限すれば、解決できる可能性があります。たとえば、次の質問に答えることができます (おそらく簡単ではありません): 浮動小数点値 X は、.0001 の整数倍に最も近い浮動小数点値ですか? (つまり、.0001 を k で乗算し、最も近い浮動小数点値に丸めると正確に X が生成されるような整数 k はありますか?)

したがって、解決策を得るには、目標をさらに説明する必要があります。ステップの任意の値または特定の値のみの解が必要ですか? 2 進浮動小数点では Step を正確に表すことができないため、それを記述する他の方法はありますか? たとえば、常に .0001 の倍数になるのでしょうか? 倍数として受け入れたい値は常に正確な数学的倍数に最も近い 2 進浮動小数点数ですか、それとも追加のエラーがある可能性がありますか?

于 2012-09-14T18:05:26.097 に答える
2

基本的な問題は、32 ビット浮動小数点数がすべての実数を正しく表現できないことです。たとえば、ユーザーが 0.1 を入力すると、フロートの値は 0.099999994 になります。

したがって、増分が 0.1 の場合、彼が 0.1 を入力したか (これは有効)、または 0.09999.. を入力したか (無効) はわかりません。

私の提案は、代わりに整数データ型を使用し、それを固定小数点数のように扱うことです。そうすれば、精度が失われることはなく、多重度を簡単に確認できます。

于 2012-09-14T19:45:38.030 に答える
0

Below will work for all decimals.

var result = Math.round( Math.round(number1 * 100000) % Math.round(number2 * 100000) ) / 100000;
于 2014-12-29T10:55:22.647 に答える
-2

あなたは浮動小数点を扱っているので、あなたの最善の策は、「近い」クローズがどれだけあるかを判断し、それを使用することです:

function IsMultipleOf(a, b) {
   var result = a % b;
   return (result < 1e-3);
}
于 2012-09-14T17:41:07.350 に答える
-2

JavaScript を使用して、浮動小数点数が別の浮動小数点数の倍数であるかどうかを判断する必要があります。

浮動小数点数を使用して実数を近似すると仮定すると、定義により、すべての浮動小数点数は別の数値の倍数になります。もちろん、浮動小数点数は実際には有理数のサブセットであるため、共通の浮動小数点除数を持たない浮動小数点数のペアが多数存在します。たとえば、仮数の素数係数が異なる 2 つの浮動小数点数には公約数がありません。指数の範囲は、正確な倍数でペアをさらに制限します。

しかし、任意の乗算係数を持つ数値を探しているのではなく、整数の除数を持つ数値を探していて、結果が選択したしきい値 (通常はイプシロンと呼ばれる) を下回っているかどうかをテストする場合があります。

例えば、機能的なスタイルの疑似コード!

fmod :: float -> float -> float
fmod a b =
    b - a * floor( b / a )

EPSILON = 1e-5;
divides_to_integer :: float -> float -> boolean
divides_to_integer a b =
    fmod(a, b) < EPSILON

fmod 関数は、JavaScript 数学ライブラリから取得する必要があります。

于 2012-09-14T17:48:16.677 に答える