SSブログ

『Java Puzzlers』とGo言語(1) [golang]

先週の金曜日のGo言語研修が終わって、懇親会(会社の食堂)まで時間があったので、『Java Puzzlers』をやってみました。

Java Puzzlers 罠、落とし穴、コーナーケース

Java Puzzlers 罠、落とし穴、コーナーケース

  • 作者: ジョシュア・ブロック
  • 出版社/メーカー: ピアソン・エデュケーション
  • 発売日: 2005/11/14
  • メディア: 大型本

もう12年前の本で、現在は絶版となっています。発売された時に、日本でJavaOneが開催されていて、印刷されたばかりのこの本が販売された頃が懐かしいです。

ところで、Javaではパズルになるものが、Go言語ではそもそもコンパイルエラーになるものが多いです。その理由の一つは、異なる整数型の混合計算をGo言語が許さないことです。初めてGo言語に触れると、その点がちょっと煩わしく感じます。でも、パズルをGo言語で書くとどうなるかを知ると、言語の違いが分かってきて面白いです。
パズル2: 変革の時(Time for a Change)

次の文章問題を考えてみてください。
トムは、$1.10 するスパークプラグを購入するために自動車部品店に行きますが、財布の中にあるのは2 ドル紙幣ばかりです。2 ドル紙幣でスパークプラグの代金を支払ったとしたら、彼は、お釣りをいくら貰うでしょうか。

この文章問題を解こうとしているのが、次のプログラムです。このプログラムは、何を表示しますか?
public class Change {
    public static void main(String args[]) {
        System.out.println(2.00 - 1.10);
    }   
}
これを実行すると結果は、0.8999999999999999となります。その理由は、1.10を浮動小数点数では正確に表現できないからです。

Go言語で同じコードを書くと次のようになります。
package main

import "fmt"

func main() {
    fmt.Println(2.00 - 1.10)
}
そして、実行結果は、0.9です。なぜ、Go言語でこうなってしまうのでしょうか?

それは、2.001.10の扱いの違いです。Go言語では、それらは「型付けなし(untyped)浮動小数点数」です。そして、Printlnの引数の式は定数リテラルの演算なので、コンパイル時に定数として計算されます。この定数計算に関しては、Go言語では言語仕様ですべのGo言語の実装に対して、次のように高い精度を要求しています。

Represent floating-point constants, including the parts of a complex constant, with a mantissa of at least 256 bits and a signed binary exponent of at least 16 bits.
しかし、いくら高い精度でもっても、正確には表現できないはずです。そこで、言語仕様では次の条件が付加されています。
Round to the nearest representable constant if unable to represent a floating-point or complex constant due to limits on precision.
つまり、定数計算の結果は、表現可能な最も近い値の定数となるのです。

もちろん、定数ではないfloat64の変数に代入してから計算すると、0.9にはなりません。
package main

import "fmt"

func main() {
    var x, y float64 = 2.00, 1.10
    fmt.Println(x - y)
}
このコードの実行結果は、0.8999999999999999です。

型付けなし定数については、『プログラミング言語Go』の「3.6.2 型付けなし定数」(p.87)でも説明されていますが、上記の丸めについては書かれていません。

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)

  • 作者: Alan A.A. Donovan
  • 出版社/メーカー: 丸善出版
  • 発売日: 2016/06/20
  • メディア: 単行本(ソフトカバー)


コメント(0) 

コメント 0

コメントを書く

お名前:[必須]
URL:
コメント:
画像認証:
下の画像に表示されている文字を入力してください。

Facebook コメント