BigInt-JavaScriptの長い演算

BigIntはJavaScriptの新しい数値プリミティブデータ型であり、任意の精度の数値を操作できます。 BigIntすると、 Number最大安全整数値を超えても、大きな整数を安全に格納および処理できます。 この記事では、 BigIntとChrome 67の新機能の使用例をいくつか見て、JavaScriptでBigIntNumberを比較します。


使用例


任意の精度の整数は、JavaScriptの多くの新しい用途を開きます。


BigIntは、数学演算でのオーバーフローエラーの防止に役立ちます。 この事実はそれ自体で無数の可能性を利用可能にします。たとえば、金融テクノロジーでは一般に、多数の数学的操作が使用されます。


JavaScriptのNumberデータ型では、 大きな数値識別子高精度のタイムスタンプを安全に表すことができません。 これは多くの場合 エラーにつながり、開発者はそれらを文字列として保存する必要があります。 BigIntこのデータは数値として表現できます。


BigIntは、 BigDecimalデータ型の可能な実装で使用できます。 これにより、操作中に精度を損なうことなく(たとえば、問題なく0.10 + 0.20 !== 0.30 )、小数値の形で金額を格納できます。


これらのケースのいずれかのJavaScriptの以前では、 BigInt機能をエミュレートするライブラリを使用する必要がありました。 BigIntが広く利用可能になると、ネイティブにサポートされているBigInt優先して、これらの依存関係を放棄することが可能になります。 これにより、実行時間のパフォーマンスが向上するだけでなく、負荷、解析、およびコンパイル時間が短縮されます。


https://habrastorage.org/webt/ep/l8/hc/epl8hchee6j7hskpzq0g_ivp1he.png
ネイティブBigIntは一般的なカスタムライブラリよりも高速です


BigIntは、新しい構文をライブラリAPI呼び出しに変換するために、必要な機能を実装するライブラリと、変換ステップが必要です。 Babelは現在、 BigIntリテラルの解析をサポートしていますが、変換できません。 したがって、 BigIntがさまざまなブラウザーとの互換性を必要とするサイトのBigIntで使用されることを期待していません。 ただし、この機能がブラウザーに表示されるようになったので、BigIntの実験を開始して、BigIntのサポートが徐々に増えることを期待できます。


現状:番号


プリミティブJavaScriptデータ型Numberは、倍精度浮動小数点Numberで表されます。 定数Number.MAX_SAFE_INTEGERは、1だけ安全に増やすことができる最大の整数が含まれています。 その値は2 ** 53-1です。


 const max = Number.MAX_SAFE_INTEGER; // → 9_007_199_254_740_991 

注:読みやすくするために、アンダースコアを区切り文字として使用して番号をグループ化します。 適切なにより、通常のJavaScript数値リテラルにこのような表記を使用できます。


1つずつ増やすと、期待される結果が得られます。


 max + 1; // → 9_007_199_254_740_992 

しかし、もう1つ増やした場合、 Numberは結果を正確に保存できません。


 max + 2; // → 9_007_199_254_740_992 

max + 1の結果は、式max + 2結果と等しくなることに注意してください。 したがって、JavaScriptでこの特定の値を取得するたびに、それが正確であるかどうかを言うことはできません。 安全な整数範囲外(つまり、 Number.MIN_SAFE_INTEGERからNumber.MIN_SAFE_INTEGERまで)の整数を使用した計算は、潜在的にNumber.MAX_SAFE_INTEGERです。 このため、安全な範囲の整数値のみに依存できます。


新規:BigInt


BigIntはJavaScriptの新しい数値プリミティブデータ型であり、任意の精度の数値を操作できます。 BigIntすると、 Number最大安全整数値を超えても、大きな整数を安全に格納および処理できます。


BigIntを作成するには、整数のリテラル表記に接尾辞nを追加するだけです。 たとえば、 123123nなり123n 。 グローバル関数BigInt(number)を使用して、数値をBigIntにキャストできます。 つまり、 BigInt(123) === 123nです。 これを使用して、上で説明した問題を解決しましょう。


 BigInt(Number.MAX_SAFE_INTEGER) + 2n; // → 9_007_199_254_740_993n 

以下に、 Number型の2つの数値を乗算する別の例を示します。


 1234567890123456789 * 123; // → 151851850485185200000 

下位桁の93を見ると、乗算の結果は7終わるはずだと主張できます( 9 * 3 === 27 )。 しかし、結果はゼロのセットで終わります。 何かがおかしかった。 BigIntもう一度試してみましょう。


 1234567890123456789n * 123n; // → 151851850485185185047n 

今回は結果が正しいです。


整数の安全な動作の制限はBigIntには適用されないため、 BigIntを使用すると、精度の低下を心配することなく長い演算を使用できます。


新しいプリミティブデータ型


BigIntはJavaScriptの新しいプリミティブデータ型であるため、独自の型を取得し、 typeof演算子が返すことができます。


 typeof 123; //'number' typeof 123n; //'bigint' 

BigIntは独立したデータ型であるため、 42n !== 42型のNumber型のNumberと厳密に等しくなるBigIntはありません(たとえば、 42n !== 42 )。 BigIntとNumber型番号を比較するには、比較を行う前に一方を他方の型に変換するか、型変換比較( == )を使用します。


 42n === BigInt(42); //true 42n == 42; //true 

ブール値にキャストする場合(たとえば、 &&または||を使用するif 、またはBoolean(int)式の結果としてなど)、 BigInt型の数値はNumber型の数値とまったく同じように動作します。


 if (0n) { console.log('if'); } else { console.log('else'); } // → logs 'else', because `0n` is falsy. 

オペレーター


BigIntはほとんどの演算子をサポートしています。 バイナリ+-*および**は通常どおり動作します。 /および%も機能し、必要に応じて結果を最も近い整数に丸めます。 ビット演算子|&<<>>および^は、負の数が追加コードとしてバイナリ形式で表される場合、型Number数と同様に型BigInt数で機能します。


 (7 + 6 - 5) * 4 ** 3 / 2 % 3; // → 1 (7n + 6n - 5n) * 4n ** 3n / 2n % 3n; // → 1n 

単項-は、負の-42n値を示すために使用できます(例: -42n 。 単項+ 、asm.jsコードを破壊するため、サポートされていません。これは、 +x常にNumberまたは例外を返すことを想定しています。


重要な点は、オペレーションでBigIntNumberを混在させることはできないということです。 暗黙的な変換は情報の損失につながる可能性があるため、これは良いことです。 例を考えてみましょう:


 BigInt(Number.MAX_SAFE_INTEGER) + 2.5; // → ?? 

結果は何と等しくなりますか? 正解はありません。 BigIntは小数を含めることはできません。また、 Numberは安全な整数の制限を超える大きな数字を正確に含めることはできません。 したがって、 BigIntおよびNumber操作では、 TypeError例外がTypeErrorます。


この規則の唯一の例外は、 === (前述)、 <および>=などの比較演算子です。これらは、精度を失うリスクを伴わない論理値を返すためです。


 1 + 1n; // → TypeError 123 < 124n; //true 

注: BigIntNumberは通常混在しないため、既存のコードをNumberからBigInt書き換えないでください。 これら2つのタイプのどちらを必要とするかを決定し、使用します。 潜在的に大きな整数で動作する新しいAPIの場合、 BigIntが最適です。 ただし、整数は安全な範囲内にあることが保証されている値に引き続き使用できます。


また、符号なしの右シフトを実行する>>>演算子は、 BigInt数には常に符号が含まれるため、意味がありません。 したがって、 >>>BigInt番号では機能しません。


API


BigIntいくつかの新しいAPIメソッドが利用可能になりました。


BigIntグローバルコンストラクターBigInt Numberコンストラクターに似ています:引数をBigInt変換します(前述のとおり)。 変換が失敗すると、 RangeErrorまたはRangeError例外がスローされます。


 BigInt(123); // → 123n BigInt(1.5); // → RangeError BigInt('1.5'); // → SyntaxError 

BigIntBigInt指定された有効ビット数に制限できる2つの関数がありますが、その数を符号または符号なしのいずれかと見なします。 BigInt.asIntN(width, value)型のvalue数を、符号を考慮してwidth指定されたビット数に制限しますBigInt.asUintN(width, value)は、値を符号なしとみなして同じことを行います。 たとえば、64ビットの数値に対する操作が必要な場合、これらのAPIを使用して適切な範囲にとどめることができます。


 //     `BigInt`, //       64-  . const max = 2n ** (64n - 1n) - 1n; BigInt.asIntN(64, max); // → 9223372036854775807n BigInt.asIntN(64, max + 1n); // → -9223372036854775808n // ^  ,     

64ビット整数の範囲(値自体に63ビット、文字に1ビット)を超えるBigIntを渡すとすぐにオーバーフローが発生することに注意してください。


BigInt使用BigIntと、他のプログラミング言語で一般的に使用される64ビットの符号付きおよび符号なし整数を正確に表すことができBigInt 。 2つの新しい型付き配列BigInt64ArrayおよびBigUint64Array 、そのような値のBigUint64Arrayを簡素化します。


 const view = new BigInt64Array(4); // → [0n, 0n, 0n, 0n] view.length; // → 4 view[0]; // → 0n view[0] = 42n; view[0]; // → 42n 

BigInt64Arrayは、その値が可能な64ビット符号付き値の制限内であることを保証します。


 //     `BigInt`, //       64-  . const max = 2n ** (64n - 1n) - 1n; view[0] = max; view[0]; // → 9_223_372_036_854_775_807n view[0] = max + 1n; view[0]; // → -9_223_372_036_854_775_808n // ^  ,     

BigUint64Arrayは、64ビットの符号なしの値に対しても同様に機能します。


BigIntお楽しみBigInt



Source: https://habr.com/ru/post/J354930/


All Articles