SSブログ

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

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

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

  • 作者: ジョシュア・ブロック
  • 出版社/メーカー: ピアソン・エデュケーション
  • 発売日: 2005/11/14
  • メディア: 大型本
パズル3: 長除法(Long Division)

このパズルは、2 つのlong 値を割るプログラムに関することなので、LongDivision と呼ばれます。被除数は一日が何マイクロ秒であるかを表し、除数は一日が何ミリ秒であるかを表しています。このプログラムは、何を表示しますか?
public class LongDivision {
    public static void main(String[] args) {
        final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000;
        final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000;
        System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY);
    }
}
このプログラムの実行結果は、5です。その理由は、Javaではint型(上記の数値リテラルはすべてint)から構成される式の演算結果の型はintなので、上記のMICROS_PER_DAYへの代入の右辺の式の計算結果はintに収まらずにオーバーフローが発生しているからです。その結果、小さな値となっており、実行結果が5なのです。

単純にGo言語で書いたコードは次のようになります(対比しやすいように、Go言語の命名規則には従っていません)。
package main

import "fmt"

func main() {
    var MICROS_PER_DAY int64 = 24 * 60 * 60 * 1000 * 1000
    var MILLIS_PER_DAY int64 = 24 * 60 * 60 * 1000
    fmt.Println(MICROS_PER_DAY / MILLIS_PER_DAY)
}
このコードの実行結果は、1000です。その理由は、右辺の式に書かれているものはすべて定数つまり「型付けなし整数」であるため、式の演算はコンパイル時に計算されます。そして、その計算結果の値も「型付けなし整数」なのです。

「型付けなし整数」の値は、型がある変数(上記の場合、int64MICROS_PER_DAY)への代入において、変数の型(int64)の取り得る値の範囲に収まれば、コンパイルされます。収まらなければ、コンパイルエラーです。

コメント(0) 

総閲覧数が累計で600万を超えました [総閲覧数]

スクリーンショット 2017-11-29 6.28.22.png
総閲覧数が600万を超えました。500万から600万は15か月でした。

コメント(0) 

『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) 

レビュー終了:『Effective Java 3rd edition』 [本]

Effective Java (3rd Edition)

Effective Java (3rd Edition)

  • 作者: Joshua Bloch
  • 出版社/メーカー: Addison-Wesley Professional
  • 発売日: 2017/12/29
  • メディア: ペーパーバック

記事「レビューした(している)これからの新刊」で、今年レビューしている本の一冊として紹介した『Effective Java 3rd Edition』のレビューが先週終了しました。

第2章から第7章までは、「Rough Cut」としてすでに「Safari」で読めるようになっています。こちらです。第3版では章が一つ追加されており、その追加された第7章「Lambdas and Streams」もSafariで読めます。

第2版では78項目でしたが、新たな第7章の7項目も含めて第3版は89項目になっています。

コメント(0) 

予約受付中『ベタープログラマ』 [本]

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

ベタープログラマ ―優れたプログラマになるための38の考え方とテクニック

  • 作者: Pete Goodliffe
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2017/12/15
  • メディア: 単行本(ソフトカバー)

昨年の6月から翻訳を行ってきた本です。優れたプログラマになるために、どのようなことを心がけるべきかについて、ソフトウェア開発の様々な側面について説明されいます。

目次は、以下の通りです。
1章 コードを気にかける
  コードへの正しい取り組み方と態度を身に付ける

第Ⅰ部 you.write(code)
2章 見かけのよい状態を維持する
  コードの表現:レイアウトと名前付け
3章 少ないコードを書く
  不必要なコードを書かない
4章 取り除くことでコードを改善する
  死んでいるコードを見つけて取り除く
5章 コードベースの過去の幽霊
  過去に書いたコードから学ぶ
6章 航路を航行する
  なじみのないコードへの取り組み方
7章 汚物の中で転げ回る
  不快でひどいコードを取り扱う
8章 そのエラーを無視するな!
  エラー処理に対する健全な態度
9章 予期せぬことを予期する
  あらゆる可能性を考慮して、頑強なコードを書く
10章 バグ狩り
  バグを見つけて修正する
11章 テストの時代
  開発者テスト:単体テスト、インテグレーションテスト、システムテスト
12章 複雑さに対処する
  不必要な複雑さを避けるために、コードをうまく設計する
13章 二つのシステムの物語
  優れた設計とひどい設計の顛末

第Ⅱ部 練習することで完璧になる
14章 ソフトウェア開発とは
  ソフトウェア開発とは何か
15章 規則に従って競技する
  開発チームの役割を明確にする規則を作る
16章 単純に保つ
  ソフトウェアの簡潔性を追い求める
17章 頭を使いなさい
  プログラマは頭を使うことができるし、そうするべきである
18章 変わらないものはない
  コードは不可侵ではなく変化する
19章 コードを再利用するケース
  コードを再利用するための健全な方法
20章 効果的なバージョンコントロール
  バージョンコントロールをうまく使う
21章 ゴールポストを抜ける
  QAチームと協業する
22章 凍結されたコードの数奇な人生
  コード凍結とは何か。そもそも必要か
23章 プリーズ・リリース・ミー
  ソフトウェアリリースを作成する

第Ⅲ部 個人的なこと
24章 学びを愛して生きる
  効果的な学び方
25章 試験に基づく開発者
  プログラミングと自動車運転の類似:どのように学び、どのように試験に合格するか
26章 チャレンジを楽しむ
  モチベーションを維持し、スキルを高く維持するための課題の見つけ方
27章 停滞を避ける
  プログラミングスキルの陳腐化を防ぐ
28章 倫理的なプログラマ
  開発者人生における倫理的な問題
29章 言語への愛
  多くのプログラミング言語を学び、使っている言語を愛する
30章 プログラマの姿勢
  プログラマの健康の改善:姿勢、目の疲労、元気の維持

第Ⅳ部 成し遂げる
31章 一生懸命ではなく、賢く
  効果的に働く:不要な作業を回避して、問題を解決する
32章 完了したときが完了
  プログラミングのタスクを明確にし、終わったときを正確に把握する
33章 今度こそ分かった……
  視野を狭くしない:問題を解決する最善な方法を見つける

第V部 人々の営み
34章 人々の力
  優れたプログラマと一緒に働く。チームでうまく働く方法
35章 原因は思考
  説明責任:自分自身と自らの働きを向上させる
36章 遠慮なく話す
  ソフトウェア開発者にとってのコミュニケーションスキル
37章 多くのマニフェスト
  ソフトウェアのマニフェストとは何か。なぜ必要か
38章 コードへの叙情歌
  間違ったソフトウェア管理の教訓

結び
訳者あとがき


コメント(0) 

第5期Go言語研修を開講しました [プログラミング言語Go研修]

11月24日(金)に、私にとっては通算第5期となるGo言語研修を某企業様向けに開講しました。受講生は、入社3年目までの若いソフトウェアエンジニアの11名で開講しました。

テキストは、従来通りに『プログラミング言語Go』です。

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

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

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

月に1日で、6か月で終了する研修コースです。事前にあらかじめ決まっているテキストの予習範囲に対して以下の予習を行ってもらいます。
  • テキストの内容に関して、疑問に思ったことや分からないことを、受講生で共有しているGoogle Drive上のGoogle Sheetに記入してもらいます。
  • 練習問題のプログラミングを行ってもらい、解答を各人のGithub上のリポジトリに入れる
予習は業務ではなく、プライベートの時間を使って行ってもらいますので、希望者だけが受講する研修です。

月に1日の業務扱いの研修は、9時30分から17時までです。研修では、質問表の質問に回答したり、質問に関連した基礎知識を説明したりします。そして、練習問題のプログラミングの解答の確認も行っていきます。研修終了後は、懇親会を行い、研修の内容も含めて、色々な話をします。

コメント(0) 

16冊目の翻訳本 [本]

翻訳本としては私にとって16冊目となる、次の本の翻訳本を12月に出版します。

Becoming a Better Programmer: A Handbook for People Who Care About Code

Becoming a Better Programmer: A Handbook for People Who Care About Code

  • 出版社/メーカー: O'Reilly Media
  • 発売日: 2014/10/03
  • メディア: Kindle版

原著は3年前に出版されています。著者のPete Goodliffeは、次の書籍の著者です。

Code Craft エクセレントなコードを書くための実践的技法 Mynavi Advanced Library

Code Craft エクセレントなコードを書くための実践的技法 Mynavi Advanced Library

  • 出版社/メーカー: マイナビ出版
  • 発売日: 2014/09/17
  • メディア: Kindle版

『プログラミング言語Go』の翻訳作業が終わった後の、2016年6月から翻訳に着手しました。一年以上を要したことになります。

『Becoming a Better Programmer』は、優れたプログラーを目指すための人のために、様々な話題が取り上げられています。40歳から始めた技術書の翻訳ですが、翻訳を行った本から多くのことをソフトウェアエンジニアとして学んできました。この本もからも多くのことを認識し直したり、学ぶことができました。

Amazonで予約注文できるようになりましたら、改めて紹介します。

12月からは、私にとって17冊目となる本の翻訳に着手する予定です。

コメント(0) 

clibと呼ばれるライブラリー開発の思い出(4) [clib]

(前回はこちら

メモリ管理ライブラリ

1990年代に開発したFuji Xerox DocuStation IM200 / AS200は、オペレーティングシステムがSolaris 2.3であったため、プロセスが存在していました。つまり、ユーザのメモリ空間に関しては、プロセスの壁があった訳です。それでも、プロセス内でのメモリ破壊のデバッグには苦労しました。

メモリ管理ライブラリのAPI設計にあたっては、メモリ空間がシステム全体で一つというVxWorks上で、どうやって効率よくメモリ関連の問題を早期に発見するかという視点で設計しました。細かな技術的な詳細は説明しませんが、メモリ管理ライブラリは以下の機能を持つように設計しました。
  • メモリをヒープゾーン(Heap Zone)と呼ばれる大きな単位で扱い、すべてのメモリ獲得は指定された特定のヒープゾーンから行う。用語「Heap Zone」は、初期のMachintoshのAPIから拝借したものです。
  • ヒープゾーンから獲得されたメモリブロックをdeleteオペレータで解放する際に、そのメモリブロックの範囲を超えて書き込みをして破壊していないかを検査する仕組み。破壊を検出した場合には、破壊を報告すると同時に、そのメモリブロックをnewオペレータで割り当てたソースコード名と行番号を表示する。
  • newオペレータで獲得されていないメモリブロック(もしくは、誤ったアドレス)をdeleteオペレータで解放しようとしていないかを検査する仕組み。
  • メモリブロックが獲得されたが初期化されていない、もしくは、解放されたことをデバッガーで調べている時に分かるようにする仕組み(初期化忘れやダングリングポインターに容易に気づく仕組み)。
  • ヒープゾーン内の現在のメモリ使用量と最大使用量を知る仕組み。
  • メモリリークを容易に検出できるようにし、リークしているメモリ ブロックがどのソースコードの何行目で獲得されたかを報告する仕組み。
今日では、このようなことを気にしないといけないような言語で開発することは少なくなっていると思います。しかし、2000年の頃、C++による大規模な組み込みシステムの開発では、これらの機能を事前に用意していないと、メモリ関連の障害によるデバッグは大変な時代でした。今から、やり直せるとしたら、C++ではなく、Go言語で作り直すと思います(訳者あとがき『プログラミング言語Go』)。

メモリ管理ライブラリはもちろんスレッドセーフに作成されており、このライブラリに基づいて、共通ライブラリとしてコレクション機能も含む「スレッドライブラリ」を設計しました。「スレッドライブラリ」は、Javaとそのライブラリに強く影響を受けたC++用ライブラリでした。

次回は、「スレッドライブラリ」について簡単に説明します。

コメント(0) 

通勤電車の書斎化(2) [朝型]

3年半前に「通勤電車の書斎化」を書いています。現在はどうなっているかというと、6社目となる現在の会社では、田園都市線(半蔵門線)で通勤するため、自宅の最寄り駅から始発(初電)の5時54分に乗車しています。

2駅で終点なので、そこで各駅停車に乗り換えます。この時間は確実に座れます。もっと遅い時間でも各駅停車には座れます。問題なのは、会社の最寄り駅までの間で、ノートPCを開いてどれだけ快適に作業ができる混み具合かということです。

田園都市線は混むことで有名ですが、遅い時間に乗車するとかなり混みます。そして、ノートPCを開いて作業ができるような状況ではなく、目の前の人がかなり近くまできます。つまり、座れても作業ができないのです。したがって、最寄り駅では始発に乗車します。そうすると、それほど混むこともなく、ノートPCを開いていても快適に作業できます。

電車内では、着脱式の覗き見防止フィルターを使っています。着脱式なので便利なのですが、ディスプレイの下(MacBookでDockのアイコンが並んでいる部分)はピッタリと張り付いていなくて少し浮いていて、ぼやっと見えます。


電車の中では会社の仕事をする訳ではなく、プライベートの翻訳作業が圧倒的に多いです。次に多いのは、技術書の原著のレビューです。どちらもないときは、技術の学習をしていたりします。今年は、ずっとある本の翻訳を行っていましたが、私の方の作業はすべて終わっています。出版は、おそらく年末になるかと思います。一方、今年レビューした技術書はこちらです。

朝は、会社の最寄り駅に到着するのが7時過ぎです。それから、スターバックスに行って、8時30分頃まで作業を続けて、それから出社します。

現在は、変則的な勤務をしており、16時に退社して、18時から20時まで家で仕事をしています。リコーに勤務していた頃と違って、API仕様・テストコード・実装を書いたり、PullRequestをレビューしたりと、終日ソフトウェア開発をしていることが多いです。そのためか、それとも、年齢的なことなのか、あるいは、朝起きてから13時間以上経過しているからかもしれませんが、16時に退社して電車は座れるのですが、疲れから30分ぐらい寝ていることが多いです。

コメント(0)