【Go言語 Golang】値の計算限界について調べてみた

みなさん、こんにちは。

今回は、Go言語でリリースしているコース「【Go言語】基礎文法からweb開発まで攻略コース」でいただいた質問で私にとっても勉強できたので紹介します。

コースの紹介は、こちら

 

 

質問内容

 

1588524_cc44_2

Udemyで受講者の方から下記の質問をいただきました。

MaxInt uint64 = 1<<64 - 1 と簡単に書いてありますが、1<<64 は uint64 の範囲を超えてしまっているのに、正しく MaxInt の値が計算できているのはなぜですか?

MaxInt uint64 = 1<<64 とすると、constant 18446744073709551616 overflows uint64  とエラーメッセージが表示されます。プログラムで扱える整数の範囲と、Goコンパイラがコンパイル時に扱える「数」の範囲は別物ということでしょうか?

 

 

オーバーフローとは?

 

データには型がある

プログラミング言語では、データを扱うために型と呼ばれるものがあります。

Go言語では、整数であればint型や文字列であればstring型など様々です。

特に数値系の型では、扱える値の大小の限界値が存在します。

それは、型を使うときに利用する2進数のビット数によって決まります。

 

例えば、ご自宅の中で本を1冊保管する時に、図書館で利用するような本棚を用意はしないですよね。適切な大きさの棚か本立てくらいで良いはずです。

いつも最大限使えるようにすればいいじゃん!と思いますが、パソコンの中で記憶して扱えるデータ量には、限度があります。そのため型によって扱える数の限度を設けて必要な時には幅広い数を利用できる型にしてプログラムをします。

 

型の扱える値を超えた場合

この場合がオーバーフローとなります。エラーとして表示されてしまいます。

実際にA Tour Of GoというGoの入門サイトで行うと下記のようにエラーが表示されます。

しかし、下記のようにするとエラーはなくなり表示されます。

値自体が範囲外のはずなのに計算はできているのが謎でした。

 

 

 

コンパイル時にどこまで計算できるか調べる

 

型に値を入れる際にオーバーフローでエラーになりますが、計算できるということはコンパイラ自体は計算できる値の幅に入っていることになります。

そこで、コンパイラが計算できない範囲はどこまでか調べました。

 

Githubで調べる

GoのソースコードはGithubに挙げられており、そこから調べていきました。

Github Golang mprint.go

この部分でMpprecという定数と比較しながら限界値を判断していました。そこで、Mpprecを検索するとGithub Golang mpfloatにMpprec=512となっていました。つまり512ビット計算までできます。2の512乗は1.340781e+154のため、これがコンパイラの計算限界値と判断できました。

 

 

試してみる

A Tour Of Goで下記のようにコードを使ってみました。

1<<512はビット計算で左に512シフトした値にします。

このビットシフトの値で512の部分が境界値ということが確認できました。

 

 

 

まとめ

 

今回は、Go言語のコンパイラで扱える値の限界について調べてみました。

最初は、OSの中身で調べるようにしていましたがGoのコンパイラの中身のコードを見るまでに時間がかかってしまいました。

検索して他の方の情報を調べるのも良いですが、根本的なソースコードがあった場合は、面倒くさくても地道にみていくべきですね。勉強になりました。


Sponsored Link

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です