題名通りの企画です。普段は厳密に知る必要のない事ですが、深掘りしてみると想定外の事が起こった次第です。
999999999999999809999~999999999999999934463 = 999999999999999900000
//ここから指数化される
999999999999999934464~1000000000000000065536 = 1e+21
1000000000000000065537~1000000000000000196607 = 1.0000000000000001e+21
1000000000000000196608 = 1.0000000000000003e+21
//Number.MAX_VALUEと等価になる最大値の羅列(309桁)
1.7976931348623157e+308 = 17976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497791
//上記より1大きくすると無限大
Infinity = 17976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497792
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``)
//64bit浮動小数 最大値
01111111 11101111 11111111 11111111 11111111 11111111 11111111 11111111(2進)
= 1.79769313486231570815e+308(10進)
01111111 11110000 00000000 00000000 00000000 00000000 00000000 00000000(2進)
= Infinity
//JavaScript
1.7976931348623157e+308~1.7976931348623158e+308 = 1.7976931348623158e+308
1.7976931348623159e+308 = 1.79769313486231580794e+308 = Infinity
//長過ぎるので改行挿入
1.7976931348623157e+308 = 1.7976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497791e+308
Infinity = 1.7976931348623158079372897140530341507993413271003782693617377
89804449682927647509466490179775872070963302864166928879109465
55547851940402630657488671505820681908902000708383676273854845
81771153176447573027006985557136695962284291481986083493647529
2719074168444365510704342711559699508093042880177904174497792e+308
//64bit浮動小数 0寄りの最小値
00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001(2進)
= 4.94065645841246544177e-324(10進)
//JavaScript
2.4703282292062328e-324~7.4109846876186981e-324 = 5e-324
2.4703282292062327e-324 = 0
JavaScriptでは指数部が-324
になると、表示される整数部は5
のみである。小数部は表示されない(5e-324
のみ)
0.000001 = 0.0000009999999999999998488689934190987163020736261387355625629425048828126
//ここから指数化で表示
9.999999999999997e-7 = 0.0000009999999999999998488689934190987163020736261387355625629425048828125
//0に等しい最大の数値(小数点以下324桁目が2、全1077桁)
0 = 0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
00000000000000000000000000000002470328229206232720882843964341106861825299013071623822127928412503
37753635104375932649918180817996189898282347722858865463328355177969898199387398005390939063150356
59515570226392290858392449105184435931802849936536152500319370457678249219365623669863658480757001
58576926990370631192827955855133292783433840935197801553124659726357957462276646527282722005637400
64854999770965994704540208281662262378573934507363390079677619305775067401763246736009689513405355
37458516661134223766678604162159680461914467291840300530057530849048765391711386591646239524912623
65388187963623937328042389101867234849766823508986338858792562830275599565752445550725518931369083
6254779186948667994968324049705821028513185451396213837722826145437693412532098591327667236328125
//整数部 1以上
1 = 1.00000000000000011102230246251565404236316680908203125
1.0000000000000002 = 1.00000000000000011102230246251565404236316680908203126
let A=["0.000000",...Array(67).fill(0)],a=0,z=A.length;
for(;++a<z;)for(let b=9;A[a]=b--,!/e/.test(+A.join``););
document.write(A.join``)
let A=["1.",...Array(53).fill(0)],a=0,z=A.length;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``>1;);
document.write(A.join``)
let A=["0.",...Array(1075).fill(0)],a=0,z=A.length;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``;);
document.write(A.join``)
まとめて広範囲
for(let n=100;--n;){
let A=[n+".",...Array(55).fill(0)],a=0,z=A.length;
for(;++a<z;)for(let b=9;A[a]=b--,+A.join``>n;);
document.write(A.join``,"<br>")
}
0に等しい最大の数値は小数点以下1075桁まで追い求める事ができた(驚愕)。ちなみに1076桁目からはずっと0が続く。なぜJavaScriptでそんな桁数まで比較できるのだろうか? JavaScriptは64bit浮動小数点数で実装しているはずだが、それだと全く精度が足りないはず…。
更に不可解なのは1と等しい最大の数値は小数点以下53桁で打ち切られる事だ。54桁目からはずっと0が続く。
309桁整数最大値については検索してみると見つかった。ここに色々と面白い情報が載っている。float8
の項目に注目だ。
数学的には、最大値は 21023 * (1+(1-(1/252))) となり、この値の負数が最小値、正数が最大値になります。その値を羅列すると
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
となります。
問題となるのは、実際に保存しておける大きな数字は179769313486231580793728971405303415079934132710037826936173778980444968292764750946649017977587207096330286416692887910946555547851940402630657488671505820681908902000708383676273854845817711531764475730270069855571366959622842914819860834936475292719074168444365510704342711559699508093042880177904174497791
です。
これは浮動小数点数の本質的な不正確さのため許容されていると思います