💨

JavaScriptの計算力、最大1075桁?

2025/02/27に公開

この物語は多倍長整数とは無縁である(多分)。我が流派の結論は最後に述べる。

Number.MAX_VALUE

その値は1.7976931348623157e+308となり、上記と等価になる最大の整数は309桁に及ぶ。

整数
17976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497791
指数表記
1.7976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497791e+308
2進表記(IEEE 754, 64 bit倍精度)
01111111 11101111 11111111 11111111 11111111 11111111 11111111 11111111

Number.MIN_VALUE

本来64bit浮動小数点数なら4.94065645841246544177e-324という値になるはずだが、表示上では5e-324で妥協している模様。JavaScriptでは指数部が-324になると、表示される整数部は5のみである。小数部は表示されない(5e-324のみ)

深掘り
2.4703282292062328e-3247.4109846876186981e-324 = 5e-324
2.4703282292062327e-324 = 0

Number.MAX_SAFE_INTEGER

その値は9007199254740991で、これは説明するまでもないかな。

Number.MIN_SAFE_INTEGER

その値は-9007199254740991、もはや説明不要の人気者。

Number.EPSILON

その値は2.220446049250313e-16。1と1より大きな最小の浮動小数点数の差。これについては多少深掘りしてみる。

1と等しい最大の数値
1 = 1.00000000000000011102230246251565404236316680908203125
上記より大きくて最も近い数値
1.0000000000000002 = 1.00000000000000011102230246251565404236316680908203126
その差を計算
let a=1.00000000000000011102230246251565404236316680908203126
	- 1.00000000000000011102230246251565404236316680908203125
console.log(a)//2.220446049250313e-16

おお、確かにその通りだ! では逆にNumber.EPSILON + 1を計算してみると…

console.log(Number.EPSILON + 1)// 1.0000000000000002

この結果に満足して頂けただろうか。ちなみにNumber.EPSILONの正確な値を探ってみると

0.000000000000000222044604925031332736629621774782981616517665087069677287701097156968899071216583251953125

小数点以下105桁まで到達。前述の計算と比べると何やらとんでもない誤差がガガガ…

//意地悪な方
 1.00000000000000011102230246251565404236316680908203126
-1.00000000000000011102230246251565404236316680908203125
=0.00000000000000000000000000000000000000000000000000001
//定義に忠実
 1.00000000000000011102230246251565404236316680908203126
-1.00000000000000000000000000000000000000000000000000000
=0.00000000000000011102230246251565404236316680908203126

<0.000000000000000222044604925031332736629621774782981616517665087069677287701097156968899071216583251953125

Infinity

Infinityと等価な最小の整数は309桁に及ぶ。前述のNumber.MAX_VALUEと等価な最大の整数より1大きい。

17976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497792
指数表記
1.7976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497792e+308
2進表記(IEEE 754, 64 bit倍精度)
01111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000

しかし、言うまでも無い事だがNumber.MAX_VALUE + 1Infinityとはならない。計算誤差が発生するのだ。Number.MAX_VALUE + 9.9792015476736e291を計算するとInfinityとなる。

指数部が負で指数化され始める数値

JavaScriptでは数値を表示しようとするとある値を境に指数化される。0以上1未満の小数について、その値は大雑把に言うと9.999999999999997e-7、厳密に言うと0.0000009999999999999998488689934190987163020736261387355625629425048828125である。
逆に指数化されない最大の小数は0.000001、より厳密には 0.0000009999999999999998488689934190987163020736261387355625629425048828126である。

指数部が正で指数化され始める数値

その値は1e+21、厳密に言うと999999999999999934464~1000000000000000065536である。

0に等しい最大の数値(物語の結論)

その値は

0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000002470328229206232720882843964341106861825299013071623822127928412503
37753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356
59515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001
58576926990370631192827955855133292783433840935197801553124659726357957462276646527282722005637400
64854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355
37458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623
65388187963623937328042389101867234849766823508986338858792562830275599565752445550725518931369083
6254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125

となる。小数点以下1075桁に及ぶ。我が流派が求められた有意義な数値としては最大の桁数である。

今までの計算方法

309桁整数最大値召喚
let A=Array(309).fill(0),a=0,z=A.length;
for(;a<z;a++)for(let b=9;A[a]=b--,+A.join``==Infinity;);
document.write(A.join``)
Number.EPSILON
let A=["0."],a=0,z=106,e=Number.EPSILON;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``>e;);
document.write(A.join``)
指数部が負で指数化され始める数値召喚
let A=["0.000000"],a=0,z=68;
for(;++a<z;)for(let b=9;A[a]=b--,!/e/.test(+A.join``););
document.write(A.join``)
1に等しい最大の数値召喚
let A=["1."],a=0,z=54;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``>1;);
document.write(A.join``)
0に等しい最大の数値召喚
let A=["0."],a=0,z=1076;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``;);
document.write(A.join``)

Discussion