BigInt-JavaScriptの長い演算

BigInt



はJavaScriptの新しい数値プリミティブデータ型であり、任意の精度の数値を操作できます。 BigInt



すると、 Number



最大安全整数値を超えても、大きな整数を安全に格納および処理できます。 この記事では、 BigInt



とChrome 67の新機能の使用例をいくつか見て、JavaScriptでBigInt



Number



を比較します。







使用例



任意の精度の整数は、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



を追加するだけです。 たとえば、 123



123n



なり123n



。 グローバル関数BigInt(number)



を使用して、数値をBigInt



にキャストできます。 つまり、 BigInt(123) === 123n



です。 これを使用して、上で説明した問題を解決しましょう。







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





以下に、 Number



型の2つの数値を乗算する別の例を示します。







 1234567890123456789 * 123; // → 151851850485185200000
      
      





下位桁の9



3



を見ると、乗算の結果は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



または例外を返すことを想定しています。







重要な点は、オペレーションでBigInt



Number



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







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





結果は何と等しくなりますか? 正解はありません。 BigInt



は小数を含めることはできません。また、 Number



は安全な整数の制限を超える大きな数字を正確に含めることはできません。 したがって、 BigInt



およびNumber



操作では、 TypeError



例外がTypeError



ます。







この規則の唯一の例外は、 ===



(前述)、 <



および>=



などの比較演算子です。これらは、精度を失うリスクを伴わない論理値を返すためです。







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





注: BigInt



Number



は通常混在しないため、既存のコードを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
      
      





BigInt



BigInt



指定された有効ビット数に制限できる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










All Articles