ポニーに人参あげた。口もと(鼻先)の動きがなんともいえない。
藤原 克則 (著)
http://www.shuwasystem.co.jp/products/7980html/2918.html
価格: 2100円(税込)(本体2000円)
単行本: 295ページ
出版社: 秀和システム (2011/03)
ISBN-10: 4798029181
ISBN-13: 978-4798029184
発売日: 2011/03
商品の寸法: 23.4 x 18.2 x 2.2 cm
ダウンロード
http://www.shuwasystem.co.jp/support/7980html/2918.html
正誤
http://www.lares.dti.ne.jp/~foozy/fujiguruma/books.html#codereview-book.errata
著者
http://www.lares.dti.ne.jp/~foozy/fujiguruma/books.html#codereview-book
★レビュー準備編
●1 レビューを効率良く進めるために
1.1 全体像を素早く掴むための準備
1.2 コードの参照性を高めるための準備
●2 レビューでの指摘を活かすために
2.1 「失敗学」とは?
2.2 失敗の分類
2.3 原因の究明
2.4 失敗への対策
2.5 添付チェックシートについて
●3 レビューでの指摘を恐れないために
3.1 「評価」と「技能」
3.2 「責任の共有」と考える
3.3 「指摘がない」のは良いことか?
3.4 「間違える」のは「難しい」から
★レビュー実践編
■機能充足性
●01 if/else文での判定条件は適切ですか?
01.01 判定条件に漏れはありませんか?
01.02 判定順序は適切ですか?
01.03 判定方法は最適化されていますか?
●02 データ型は適切ですか?
02.01 変数型の値域は十分ですか?
02.02 比較対象の型は一致していますか?
●03 ループの終了判定は妥当ですか?
03.01 必要な変数がすべて初期化されていますか?
03.02 終了判定の対象は適切な変数ですか?
03.03 終了条件は適切ですか?
03.04 更新処理に漏れはありませんか?
03.05 構文選択は妥当ですか?
●04 switch文のcaseラベル列挙は十分ですか?
04.01 caseラベルの列挙に漏れはありませんか?
04.02 default節は明記してありますか?
●05 引数チェックは十分ですか?
05.01 前提条件の確認を実装していますか?
05.02 前提条件を明記していますか?
●06 戻り値チェックは十分ですか?
06.01 戻り値の仕様は確認済みですか?
06.02 獲得したリソースの解放は適切ですか?
■リソース消費
●07 引数チェックが多過ぎませんか?
07.01 引数チェックは十分軽量ですか?
07.02 関数の呼び出し関係を把握していますか?
●08 戻り値チェックが多過ぎませんか?
08.01 戻り値チェックは十分軽量ですか?
08.02 関数の仕様は確認済みですか?
●09 関数の局所変数が多過ぎませんか?
09.01 未使用変数はないですか?
09.02 通用範囲は妥当ですか?
●10 各行の負荷を把握していますか?
10.01 引数による負荷の変動を把握していますか?
10.02 ループ内での関数呼び出しは軽いですか?
10.03 排他獲得状態は把握していますか?
●11 似たような処理があちこちにありませんか?
11.01 その処理は本当に必要ですか?
11.02 その処理は集約できませんか?
11.03 処理を似せる工夫はしていますか?
●12 不要な条件判定をしていませんか?
12.01 引数/戻り値チェックとの重複はありませんか?
12.02 その条件は成立し得ますか?
●13 構造体渡しは必要ですか?
13.01 構造体のサイズは妥当ですか?
13.02 他から参照されていませんか?
13.03 コンストラクタ/デストラクタは妥当ですか?
●14 不要な関数呼び出しをしていませんか?
14.01 関数の戻り値を処理に使っていますか?
14.02 その関数には副作用がありますか?
●15 関数呼び出しのコストを把握していますか?
15.01 引数の数は妥当ですか?
15.02 ライブラリ形式は妥当ですか?
●16 例外に頼り過ぎていませんか?
16.01 条件判定で済みませんか?
●17 スレッド間同期の方法は適切ですか?
17.01 同期の必要性は認識していますか?
17.02 同期手順は適切ですか?
17.03 同期方法は適切ですか?
17.04 同期対象は明確ですか?
●18 アルゴリズムやデータ構造の選択は適切ですか?
18.01 最大データ量の見積もりはどの程度ですか?
18.02 改変頻度の見積もりはどの程度ですか?
18.03 どんなアクセス方式を想定していますか?
●19 コンパイラの最適化に期待し過ぎていませんか?
19.01 関数横断での最適化を期待していませんか?
19.02 メモリ配置での最適化を期待していませんか?
●20 ファイルアクセスは妥当ですか?
20.01 ファイルアクセスは最小限ですか?
20.02 mmap()の使用は検討済みですか?
20.03 ディレクトリ構成は妥当ですか?
20.04 システムの制限は把握していますか?
■実行安全性
●21 入力データは検証済みですか?
21.01 どこまで信用できるデータですか?
21.02 サイズの妥当性は検証済みですか?
21.03 内容の妥当性は検証済みですか?
●22 スタック消費量は妥当ですか?
22.01 局所変数は最小限ですか?
22.02 関数呼び出しの深さは妥当ですか?
●23 ヒープ消費量は妥当ですか?
23.01 総データ量の見積もりは済んでいますか?
23.02 未使用領域を解放していますか?
●24 スレッド数は十分ですか?
24.01 スレッド数は十分ですか?
24.02 スレッド数が過剰ではないですか?
●25 ファイル操作は妥当ですか?
25.01 ファイル更新手順は妥当ですか?
25.02 ファイルシステム境界は意識していますか?
25.03 時間当たりの転送量の見積もりは済んでいますか?
●26 ネットワークアクセスは妥当ですか?
26.01 連携先との接続障害に備えていますか?
26.02 連携タイミングに関する前提は妥当ですか?
26.03 時間当たりの転送量の見積もりは済んでいますか?
●27 異常が検出された際の挙動は適切ですか?
27.01 継続可能な異常ですか?
27.02 不要なリソースは解放していますか?
27.03 異常への対応位置は妥当ですか?
■保守性
●28 横に長いコードになっていませんか?
28.01 ループや条件判定の入れ子が多過ぎませんか?
28.02 関数引数が多過ぎませんか
28.03 式が複雑過ぎませんか?
●29 空行を適切に挿入していますか?
29.01 関連する処理はどれですか?
29.02 関連するデータはどれですか?
●30 プロジェクトのコーディング規約に従っていますか?
30.01 プロジェクトにコーディング規約はありますか?
30.02 規約チェック用のツールはありますか?
●31 自分のコーディングスタイルは一貫していますか?
31.01 各行の体裁が一貫していますか?
31.02 関数宣言の体裁が一貫していますか?
31.03 関数定義の体裁が一貫していますか?
●32 機能を詰め込み過ぎていませんか?
32.01 引数による条件判定が多過ぎませんか?
32.02 関数の行数が多過ぎませんか?
●33 変更をどこまで想定していますか?
33.01 その値は変更されませんか?
33.02 その処理は変更されませんか?
●34 名前付けは適切ですか?
34.01 具体性はありますか?
34.02 対称性/相似性はありますか?
34.03 データ型が変わっても通じますか?
■拡張性
●35 無駄な拡張性にこだわっていませんか?
35.01 どの程度の拡張性を想定していますか?
35.02 安全性は考慮されていますか?
●36 十分な情報を受け渡していますか?
36.01 実現される機能範囲は想定済みですか?
36.02 情報の受け渡し方法は妥当ですか?
■テスト容易性
●37 環境に依存する箇所は把握していますか?
37.01 別のホスト上でもテストできますか?
37.02 別のシステム構成でもテストできますか?
37.03 別のOS/CPUアーキテクチャ上でもテストできますか?
●38 テスト環境の構築は簡単ですか?
38.01 必要なソフトウェアの入手は簡単ですか?
38.02 必要なハードウェアの入手は簡単ですか?
38.03 事前状態の作成は簡単ですか?
●39 日付と時刻の扱いを考えていますか?
39.01 テストデータの準備はどうしていますか?
39.02 「今日」「今」を扱いますか?
●40 どこまで細分化したテストを行えますか?
40.01 テスト対象関数は呼び出せますか?
40.02 組み合わせバリエーションは把握済みですか?
40.03 エラー系のテストはできますか?
40.04 タイミング依存の処理はテストできますか?
あとがき
レビューチェックシート
分類先決定のためのフローチャート
珈琲館でもらった「謹賀新年」のストラップ。
何気なく入ったが、もらえるとは思わなかった。
3が日はくれるのかな。
練習問題(20110815版)解答例
================================================================================
■Q1. 身長(m)と体重(kg)を入力してBMIを求めて表示する。
BMIは次の式で求まる。
体重 / 身長^2
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q1. 身長(m)と体重(kg)を入力してBMIを求めて表示する。
BMIは次の式で求まる。
体重 / 身長2
<script type="text/javascript">
var height = Number(prompt("身長入力(m)", 0));
var weight = Number(prompt("体重入力(kg)", 0));
document.write(weight / (height * height) + "
");
</script>
</body>
</html>
---
■Q2. 2つの数値を入力する。
入力した2つの数値を、小さい順に並べて表示する。
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q2. 2つの数値を入力する。
入力した2つの数値を、小さい順に並べて表示する。
<script type="text/javascript">
var i1 = Number(prompt("1番目の数値を入力してください。", "0"));
var i2 = Number(prompt("2番目の数値を入力してください。", "0"));
document.write("入力した数値は " + i1 + ", " + i2);
document.write("
");
document.write("小さい順に並べると ... ");
if (i1
");
</script>
</body>
</html>
---
■Q3. 3つの数値を入力する。
入力した3つの数値の中の最小値を表示する。
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q3. 3つの数値を入力する。
入力した3つの数値の中の最小値を表示する。
<script type="text/javascript">
var i1 = Number(prompt("1番目の数値を入力してください。", "0"));
var i2 = Number(prompt("2番目の数値を入力してください。", "0"));
var i3 = Number(prompt("3番目の数値を入力してください。", "0"));
document.write("入力した数値は " + i1 + ", " + i2 + ", " + i3);
document.write("
");
document.write("最小値は ... ");
var min = i1;
if (min > i2) {
min = i2;
}
if (min > i3) {
min = i3;
}
document.write(min);
document.write("
");
</script>
</body>
</html>
---
■Q4. 数値を入力する。
入力した数値の符号を表示する。
表示は、「-」、「0」、「+」でかまわない。
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q4. 数値を入力する。
入力した数値の符号を表示する。
表示は、「-」、「0」、「+」でかまわない。
<script type="text/javascript">
var i1 = Number(prompt("数値を入力してください。", "0"));
document.write("入力した数値は " + i1);
document.write("
");
document.write("符号は ... ");
if (i1 < 0) {
document.write("「-」");
} else if (i1 == 0) {
document.write("「0」");
} else {
document.write("「+」");
}
document.write("<br/>");
</script>
</body>
</html>
---
■Q5. 数値を入力する。
入力した数値が、1~12の範囲に入っているかどうかを確認する。
表示は、「入っている」、「入っていない」でかまわない。
(ヒント) 範囲に入っていないものからチェックするとよい
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q5. 数値を入力する。
入力した数値が、1~12の範囲に入っているかどうかを確認する。
表示は、「入っている」、「入っていない」でかまわない。
(ヒント) 範囲に入っていないものからチェックするとよい
<script type="text/javascript">
var i1 = Number(prompt("数値を入力してください。", "0"));
document.write("入力した数値は " + i1);
document.write("
");
document.write("1~12の範囲に ... ");
if (i1 < 1) {
document.write("入っていない");
} else if (i1 > 12) {
document.write("入っていない");
} else {
document.write("入っている");
}
document.write("
");
</script>
</body>
</html>
---
■Q6. 3-for2.html で、年も選択できるようにする。
年の範囲は、1990年~2020年とする。
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q6. 3-for2.html で、年も選択できるようにする。
年の範囲は、1990年~2020年とする。
<form>
誕生日:
<select>
<script type="text/javascript">
for(var i = 1990; i <= 2020; i++){
document.write("<option>" + i + "</option>");
}
</script>
</select>
年
<select>
<script type="text/javascript">
for(var i = 1; i <= 12; i++){
document.write("<option>" + i + "</option>");
}
</script>
</select>
月
<select>
<script type="text/javascript">
for(var i = 1; i <= 31; i++){
document.write("<option>" + i + "</option>");
}
</script>
</select>
日
</form>
</script>
</body>
</html>
---
■Q7. 数値を入力する。
入力された数分、★を横に並べて表示する。
(ヒント) 1個の★を表示する文を繰り返す
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q7. 数値を入力する。
入力された数分、★を横に並べて表示する。
(ヒント) 1個の★を表示する文を繰り返す
<script type="text/javascript">
var i1 = Number(prompt("数値を入力してください。", "0"));
document.write("★を " + i1 + " 個並べる ...
");
for (var i = 1; i <= i1; i++) {
document.write("★");
}
</script>
</body>
</html>
---
■Q8. 1~100の間にある3の倍数を表示する。
(結果) 3 6 9 12 ... 99
(ヒント)
for文で、カウンターを更新する式を+3ずつにする
または
if文で、カウンターの値が3の倍数かどうかを判断して、3の倍数のときだけ表示する
なお、カウンターを3で割ったときの余りが0のとき、3の倍数である。
(応用)
3の倍数だけでなく、3のつく数字も表示する
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<body>
Q8. 1~100の間にある3の倍数を表示する。
(結果) 3 6 9 12 ... 99
(ヒント)
for文で、カウンターを更新する式を+3ずつにする
または
if文で、カウンターの値が3の倍数かどうかを判断して、3の倍数のときだけ表示する
なお、カウンターを3で割ったときの余りが0のとき、3の倍数である。
(応用)
3の倍数だけでなく、3のつく数字も表示する
<script type="text/javascript">
for (var i = 3; i <= 100; i += 3) {
document.write(i);
document.write(" ");
}
</script>
別解
<script type="text/javascript">
for (var i = 1; i <= 100; i++) {
if ((i % 3) == 0) {
document.write(i);
document.write(" ");
}
}
</script>
応用
<script type="text/javascript">
for (var i = 1; i <= 100; i++) {
if ((i % 3) == 0) { // 3の倍数
document.write(i);
document.write(" ");
} else if ((i % 10) == 3) { // 1桁目が3
document.write(i);
document.write(" ");
} else if ((30 <= i) && (i <= 39)) { // 30台の数字
document.write(i);
document.write(" ");
}
}
</script>
</body>
</html>
---
■Q9. 「指定された数分、★を横に並べて表示する」関数 print_star(num) を作る。
この数は、promptを使って入力する。
(応用1)
この関数を利用して、★を正方形に並べる。
(結果例) 3つの場合
★★★
★★★
★★★
(応用2)
この関数を利用して、★を直角三角形に並べる。
(結果例) 3つの場合
★
★★
★★★
---
<html>
<head>
<title>JavaScript</title>
<style>
.question {background-color: #CCFFFF}
.answer {background-color: #CCFF99}
</style>
</head>
<script type="text/javascript">
function print_star(num) {
for (var i = 1; i <= num; i++) {
document.write("★");
}
}
</script>
<body>
Q9. 「指定された数分、★を横に並べて表示する」関数 print_star(num) を作る。
この数は、promptを使って入力する。
(応用1)
この関数を利用して、★を正方形に並べる。
(結果例) 3つの場合
★★★
★★★
★★★
(応用2)
この関数を利用して、★を直角三角形に並べる。
(結果例) 3つの場合
★
★★
★★★
<script type="text/javascript">
var i1 = Number(prompt("数値を入力してください。", "0"));
document.write("★を " + i1 + " 個並べる ...
");
print_star(i1);
</script>
(応用1)
<script type="text/javascript">
for (var i = 1; i
");
}
</script>
(応用2)
<script type="text/javascript">
for (var i = 1; i
");
}
</script>
</body>
</html>
---
練習問題(20110815版)
================================================================================
Q1. 身長(m)と体重(kg)を入力してBMIを求めて表示する。
BMIは次の式で求まる。
体重 / 身長^2
Q2. 2つの数値を入力する。
入力した2つの数値を、小さい順に並べて表示する。
Q3. 3つの数値を入力する。
入力した3つの数値の中の最小値を表示する。
Q4. 数値を入力する。
入力した数値の符号を表示する。
表示は、「-」、「0」、「+」でかまわない。
Q5. 数値を入力する。
入力した数値が、1~12の範囲に入っているかどうかを確認する。
表示は、「入っている」、「入っていない」でかまわない。
(ヒント) 範囲に入っていないものからチェックするとよい
Q6. 3-for2.html で、年も選択できるようにする。
年の範囲は、1990年~2020年とする。
Q7. 数値を入力する。
入力された数分、★を横に並べて表示する。
(ヒント) 1個の★を表示する文を繰り返す
Q8. 1~100の間にある3の倍数を表示する。
(結果) 3 6 9 12 ... 99
(ヒント)
for文で、カウンターを更新する式を+3ずつにする
または
if文で、カウンターの値が3の倍数かどうかを判断して、3の倍数のときだけ表示する
なお、カウンターを3で割ったときの余りが0のとき、3の倍数である。
(応用)
3の倍数だけでなく、3のつく数字も表示する
Q9. 「指定された数分、★を横に並べて表示する」関数 print_star(num) を作る。
この数は、promptを使って入力する。
(応用1)
この関数を利用して、★を正方形に並べる。
(結果例) 3つの場合
★★★
★★★
★★★
(応用2)
この関数を利用して、★を直角三角形に並べる。
(結果例) 3つの場合
★
★★
★★★
http://www.metro-net.co.jp/seibu/index.htm
ミートソース。
デザートは、プリンアラモード。1000円するだけあって、かなりのボリューム感。
使ってみると便利かしらん。自分の考えをまとめるツールとしてつかえそう。
http://twitter.com/marunomaruno
ついでに、Twilogも始める。
http://twilog.org/marunomaruno
これは、Twitterのツイート(つぶやき)をブログ形式で保存することができる。ログの昨日が欲しかったから、わりと重宝しそう。
http://twilog.org/
---
Android2.2.1
5インチモバイルタブレット、手のひらサイズでは一番大きいサイズ
画面が傷つきにくい、ゴリラグラス
CPU1GHz Snapdragon QSD8250
500万画素CMOSカメラ
ROM2.5GB
RAM512MB
解像度800×480 TFT液晶65536色
http://www1.jp.dell.com/jp/ja/home/mobile-accessories/mobile-streak/pd.aspx?refid=mobile-streak&cs=jpdhs1&s=dhs
---
http://mb.softbank.jp/mb/smartphone/product/001dl/
---
今のところ、気づいた不便な点
・電源ON時の最初のパスワード入力画面の向きが横で固定されている。
・たて画面だと、ソフトキーボードが携帯電話のキーボードに固定されており、ASCII キーボードにならない。
→ わたしの勘違い。単に、たて画面用と横画面用の設定が分かれていただけ。横用しか設定していなかった。たて用の設定もしたら、縦でもASCIIキーボードが出てきた。(2011-06-21 追記)
http://www013.upp.so-net.ne.jp/kojyo/
ヨーロッパの古城という感じ。地下。
階段の正面に、ステンドグラスのようなもの。
中は意外と広い。城壁を模した壁で、2つに区切られている感じ。正面には、大きいステンドグラス。天井はシャンデリア。天井も高くてよいね。
ナポリタンとアイスコーヒーを頼む。
ナポリタンおいしい。具はあまりない。青海苔がかかっていた。
そして、チョコレートパフェ。わたしごのみの、下まで生クリームがつまっている。果物は冷凍ではない。
http://sharaku2011.jp/
東京国立博物館平成館
11:00過ぎにつく。チケット売り場に行列なし。入口にも行列なし。
ただ、会場の入口のところでは、少し混雑。
音声ガイドに、落語家・春風亭昇太さん(笑点メンバー)。
まずは、写楽以前。
そして、写楽。
写楽と、同時代の他の画家の作品が並列しあったり、
同じ写楽の同じ作品だが、刷が違うもの、保存状態が違うものを並べたり、いろいろと比較できるようになっていた。
なかなかおもしろい企画。
解説にもあったが、写楽は初期のものの方がよい感じ。
後半のものは、はんこ(もともと版画なので、はんこといえばそうだが。。。)になったような感じかな。
2時間近くいた。
昨日の藤代清治展と連続だったからか、目がけっこう痛くなった。
http://www.seiji-fujishiro.com/
もう最後の週なので、11:10くらいについたが、行列。20分くらい並んで入る。
中も満員状態。
自宅、ということだからか、鳥や魚、猫、サルキー犬なんかがお迎え。まあ、サルキー犬は遠くにいて、お迎えという感じではなかったが。
また、ケロヨンなどのキャラクターも置いてあった。
また、骨董市で買った、というトラの剥製、ミシンなども展示。
そして、当然だが、影絵がすごくよい。
展覧会としてはめずらしく写真撮影OKなので、撮ってきたが、写真でみるとまた、一味違う感じ。
タイトルは忘れたが、アパートの影絵の写真などは、実物よりも写真の方がより立体的な感じだった。
光の具合かな。
カルピスのサービスもある。
1時間ほどいて、帰る。
帰りには、行列がさらに延長していた。これは、1時間以上待つかな、という感じになっていた。
著者 中村薫
価格 3360円(税込)(本体3200円)
ISBN 978-4-7980-2981-8
発売日 2011/5/24
判型 B5変
色数 1色
ページ数 352
CD/DVD -
対象読者 中級
http://www.shuwasystem.co.jp/products/7980html/2981.html
素数の判定 ================================================================================ つぎのアルゴリズムで、素数を判定してみました。また、実行時間も測定しています。 1. 1~1億までの範囲の素数表引き 2. 試し割りアルゴリズム 3. フェルマーの因数分解アルゴリズム 4. 正規表現を利用 参考までに、 5. BigIntegerのisProbablePrime()メソッドによる判定 それぞれのかかった時間(ミリ秒)を記します。時間は、それぞれ、3~5回実行したものの 平均です。判定する範囲と個数は違いますが、参考まで。 なお、時間の確認はJUnitの結果です。 --------------- --------- ----------------------- 1~999 99990001~99999999の奇数 --------------- --------- ----------------------- 1. 素数表 0 0.008 2. 試し割り 0 0.360 3. フェルマー 0.008 538,223.238 4. 正規表現 0.312 - 5. BigInteger 0.357 0.143 --------------- --------- ----------------------- フェルマーの因数分解アルゴリズムは、かなり遅いです。これは、計算のたびに平方根を 計算しているからです。因数がsqrt(n)に近い場合は効率はよいですが、そうでない場合 は実用に耐えそうにありません。 正規表現は考えは面白いですが、1並び数R(n)を作るのが大変です。実際に、R(99990001) は、「java.lang.OutOfMemoryError: Java heap space」で動きません。 上記の実行時間の大半はR(n)を作っている時間でしょう。 BigIntegerのisProbablePrime()メソッドでは、99990001~99999999の奇数の方が速いので 驚きです。 ■1. 1~1億までの範囲の素数表引き 1億までの素数は、 兵庫県立明石北高等学校のホームページ http://www.hyogo-c.ed.jp/~meihoku-hs/club/astronomy-p.html からダウンロードしたファイルをを使いました。 また、表引きは2分検索として、ArraysクラスのbinarySearch()メソッドを使いました。 ■2. 試し割りアルゴリズム 3以上の奇数の場合に、3,5,7, ..., sqrt(n) までで割って、割り切れれば合成数、いず れの数値でも割り切れなければ素数になります。 ■3. フェルマーの因数分解アルゴリズム 3以上の奇数nとします。 n = x2 - y2 = (x - y)(x + y)、x >= y >= 0 となるような非負整数 x、y を見つける。見つかれば、(x - y)、(x + y) は n の因数と なる。 n が平方数の場合は、n = x2 として、y = 0 となる。因数は、x。 n が平方数でない、すなわち、y > 0 のとき、 x = sqrt(n + y2) > sqrt(n) なので、x = [sqrt(n)] から探索を始めればよい。 また、探索の終わりは、nの因数を見つけることなので、nの半分まででよい。 すなわち、n は奇数であるので、(n + 1) / 2 になるまで因数が見つからなければ探索終 了してよい。 ■4. 正規表現を利用 ネットで調べていたら、「正規表現で素数判定」 http://d.hatena.ne.jp/ytakano/20100721/1279736214 というサイトを見つけました。 指定された正整数n(int型の最大値以下)が素数がどうかを判断するのに、nの1並び数 R(n) = (10n - 1) / 9 の文字列表現が、次の正規表現とマッチすれば合成数である。 ^1?$|^(11+?)\1+$ なかなか、面白そうなので、試してみました。ただ、このままでもよいのですが、試し割 りアルゴリズムでも、フェルマーの因数分解アルゴリズムでも、3以上の奇数に限定して いるので、正規表現でも3以上の奇数限定にしました。正規表現はつぎのようになります。 ^(1(11)+?)\1+$ □メタ記号 ----- ---------------------------------------------------- 記号 意味 ----- ---------------------------------------------------- ^ 行の先頭 $ 行の末尾 X+? X、1 回以上(最短一致数量子) (X) X、前方参照を行う正規表現グループ \n マッチした n 番目の前方参照を行う正規表現グループ X+ X、1 回以上(最長一致数量子) ----- ---------------------------------------------------- □動作のロジック 1(11)+? なので、"111" と最短一致でマッチするかを確認する。これは3以上の奇数であ れば必ずマッチする。 (1(11)+?)\1 は、"111" と最短一致でマッチしたときの1番目のグループなので、これは 文字列 "111" を意味する。 3の場合は、"111" なので、最短一致でマッチした残り "" と、 (111)+ がマッチするか を確認し、 もうマッチしないので、素数となる。 5の場合は、"11111" なので、最短一致でマッチした残り "11" と、 (111)+ がマッチす るかを確認し、マッチしない。 つぎに、1(11)+? なので、"11111" と最短一致でマッチするかを確認する。 マッチするので、残り "" が (11111)+ とマッチするか確認し、これもマッチしないので 素数となる。 9の場合は、"111111111" なので、最短一致でマッチした残り "111111" と、 (111)+ がマッチするかを確認し、これはマッチする。したがって、合成数となる。 以下、3の倍数は、(111)+ でマッチするので、合成数になる。 25の場合は、最短一致でマッチした残り "11...1"(22個) と、(111)+ がマッチするかを 確認し、これはマッチしない。 つぎに、1(11)+? なので、"11111" と最短一致でマッチするかを確認する。 マッチするので、残り "11...1"(20個) が (11111)+ とマッチするか確認し、これはマッ チする。 したがって、合成数となる。 以下、5の倍数は、(11111)+ でマッチするので、合成数になる。 いくつかの数値についてつぎにまとめる。 --- --------- -------------------------- ------ ------ 数 最短一致 グループのマッチ 結果 判定 --- --------- -------------------------- ------ ------ 3 111 "" と (111)+ false 素数 --- --------- -------------------------- ------ ------ 5 111 "11" と (111)+ false 11111 "" と (11111)+ false 素数 --- --------- -------------------------- ------ ------ 7 111 "1111" と (111)+ false 11111 "11" と (11111)+ false 1111111 "" と (1111111)+ false 素数 --- --------- -------------------------- ------ ------ 9 111 "111111" と (111)+ true 合成数 --- --------- -------------------------- ------ ------ 25 111 "111"(22個) と (111)+ false 11111 "111"(20個) と (11111)+ true 合成数 --- --------- -------------------------- ------ ------ 77 111 "111"(74個) と (111)+ false 11111 "111"(72個) と (11111)+ false 1111111 "111"(70個) と (1111111)+ true 合成数 --- --------- -------------------------- ------ ------ ■5. BigIntegerのisProbablePrime()メソッドによる判定 ソースコードをみると、つぎの2つの方法を使っている。 Miller-Rabin 法 Lucas-Lehmer 法 isProbablePrime()メソッドは、名前のとおり、素数である可能性が高い場合にtrue、必 ず合成数である場合にfalseが返るので、今回のテストでも、素数なのに合成数と判定さ れることがあった。 このメソッドは、呼び出し側が許容しない 確率の尺度を引数で渡せる。今回は、4を渡し たので、trueで、素数である確率は 1 - 1/24 = 1 - 1/16 = 0.9375 である。 ■プログラム --- import java.io.File; import java.io.FileNotFoundException; import java.math.BigInteger; import java.util.Arrays; import java.util.Scanner; import java.util.regex.Pattern; public class Factorization02 { /** * べき乗演算子の文字列表現 */ public static final String POWER_OPERATOR = "**"; /** * 正規表現を使って素数を判断するパターン(3以上の奇数に対応) */ public static Pattern PRIME_NUMBER_REGEX_ODD = Pattern.compile("^(1(11)+?)\\1+$"); /** * 100000000以下の素数の配列 */ private static int[] PRIME_NUMBERS_TABLE = new int[5761455]; static { read("prime.txt"); } /** * 単純なアルゴリズムで、指定された正整数が素数がどうかを判断する。 * @param n 正整数 * @return 素数の場合true */ public boolean isPrimeNumberBySimple(long n) { if (n < 1) { throw new IllegalArgumentException("n = " + n); } if (n == 1) { return false; } else if (n == 2) { return true; } else if ((n % 2) == 0) { return false; } for (int i = 3; i <= (int) Math.sqrt(n); i += 2) { if (n % i == 0) { return false; } } return true; } /** * フェルマーの素因数分解アルゴリズムで、指定された正整数が素数がどうかを判断する。 * @param n 正整数 * @return 素数の場合true */ public boolean isPrimeNumberByFermat(long n) { if (n < 1) { throw new IllegalArgumentException("n = " + n); } if (n == 1) { return false; } else if (n == 2) { return true; } else if ((n % 2) == 0) { return false; } long x = (long) Math.sqrt(n); if (n == x * x) { return false; // n は合成数 } for (x++; x < (n + 1) / 2; x++) { double dy = Math.sqrt(x * x - n); long y = (long) dy; if ((y * y) == (x * x - n) ) { // y が整数の場合は、合成数 return false; // n = (x - y)(x + y) } } return true; // n は素数 } /** * 正規表現で、指定された正整数n(int型の最大値以下)が素数がどうかを判断する。 * 正整数が3以上の奇数であれば、nの1並び数(R(n) = (10n - 1) / 9)の文字列表現が * 次の正規表現とマッチすれば合成数である。 * ^(1(11)+?)\1+$ * @param n int型の最大値以下の正整数 * @return 素数の場合true */ public boolean isPrimeByRegex(long n) { if (n < 1 || n > Integer.MAX_VALUE) { throw new IllegalArgumentException("n = " + n); } if (n == 1) { return false; } else if (n == 2) { return true; } else if ((n % 2) == 0) { return false; } // 1並び数を作成する StringBuilder nn = new StringBuilder((int) n); nn.append("1"); for (long i = 0; i < n / 2; i++) { nn.append("11"); } return !PRIME_NUMBER_REGEX_ODD.matcher(nn.toString()).matches(); } /** * 素数表を使って、指定された正整数(100000000以下)が素数がどうかを判断する。 * @param n 100000000以下の正整数 * @return 素数の場合true */ public boolean isPrimeByTable(long n) { if (n < 1 || n > 100000000) { throw new IllegalArgumentException("n = " + n); } return Arrays.binarySearch(PRIME_NUMBERS_TABLE, (int) n) >= 0; } /** * BigIntegerで、指定された正整数が素数がどうかを判断する。 * @param n 正整数 * @return 素数の可能性がある場合true、必ず合成数である場合false */ public boolean isProbablePrimeByBigInteger(long n, int certainty) { if (n < 1) { throw new IllegalArgumentException("n = " + n); } return new BigInteger(Long.toString(n)).isProbablePrime(certainty); // n は素数 } private static int read(String fileName) { int i = 0; try { Scanner in = new Scanner(new File(fileName)); for (i = 0; i < PRIME_NUMBERS_TABLE.length && in.hasNextInt(); i++) { PRIME_NUMBERS_TABLE[i] = in.nextInt(); } } catch (FileNotFoundException e) { System.out.println(e); } return i; } } --- ■テスト用のプログラム --- import java.util.Arrays; import junit.framework.TestCase; public class Factorization02Test extends TestCase { private static final int[] PRIME_NUMBERS_1_999 = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113, 127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193, 197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257, 263, 269, 271, 277, 281, 283, 293, 307, 311, 313, 317, 331, 337, 347, 349, 353, 359, 367, 373, 379, 383, 389, 397, 401, 409, 419, 421, 431, 433, 439, 443, 449, 457, 461, 463, 467, 479, 487, 491, 499, 503, 509, 521, 523, 541, 547, 557, 563, 569, 571, 577, 587, 593, 599, 601, 607, 613, 617, 619, 631, 641, 643, 647, 653, 659, 661, 673, 677, 683, 691, 701, 709, 719, 727, 733, 739, 743, 751, 757, 761, 769, 773, 787, 797, 809, 811, 821, 823, 827, 829, 839, 853, 857, 859, 863, 877, 881, 883, 887, 907, 911, 919, 929, 937, 941, 947, 953, 967, 971, 977, 983, 991, 997, }; private static final int[] PRIME_NUMBERS_99990001_99999999 = { 99990001, 99990029, 99990043, 99990049, 99990053, 99990083, 99990091, 99990113, 99990139, 99990161, 99990181, 99990239, 99990263, 99990281, 99990287, 99990299, 99990307, 99990329, 99990337, 99990389, 99990419, 99990461, 99990467, 99990487, 99990491, 99990493, 99990511, 99990533, 99990547, 99990551, 99990571, 99990577, 99990581, 99990587, 99990589, 99990641, 99990647, 99990679, 99990703, 99990731, 99990739, 99990757, 99990799, 99990871, 99990887, 99990893, 99990911, 99990929, 99990967, 99990971, 99990973, 99991009, 99991033, 99991049, 99991063, 99991081, 99991103, 99991109, 99991207, 99991237, 99991249, 99991271, 99991273, 99991277, 99991303, 99991343, 99991363, 99991379, 99991387, 99991447, 99991481, 99991499, 99991517, 99991519, 99991559, 99991561, 99991583, 99991609, 99991667, 99991673, 99991687, 99991721, 99991733, 99991753, 99991757, 99991769, 99991789, 99991819, 99991831, 99991877, 99991891, 99991897, 99991901, 99991933, 99991937, 99991951, 99991981, 99991987, 99991999, 99992027, 99992051, 99992059, 99992089, 99992099, 99992119, 99992141, 99992149, 99992161, 99992173, 99992209, 99992213, 99992219, 99992239, 99992251, 99992303, 99992309, 99992311, 99992363, 99992381, 99992401, 99992413, 99992429, 99992437, 99992447, 99992449, 99992461, 99992467, 99992471, 99992483, 99992509, 99992527, 99992533, 99992539, 99992617, 99992671, 99992681, 99992747, 99992771, 99992773, 99992777, 99992791, 99992797, 99992803, 99992807, 99992813, 99992831, 99992843, 99992869, 99992897, 99992903, 99992911, 99992917, 99992939, 99992941, 99992947, 99992993, 99993001, 99993053, 99993071, 99993097, 99993109, 99993119, 99993161, 99993163, 99993169, 99993193, 99993199, 99993211, 99993253, 99993263, 99993281, 99993287, 99993317, 99993329, 99993331, 99993343, 99993349, 99993359, 99993407, 99993419, 99993427, 99993433, 99993449, 99993461, 99993463, 99993469, 99993497, 99993511, 99993527, 99993583, 99993601, 99993611, 99993671, 99993679, 99993743, 99993767, 99993781, 99993787, 99993799, 99993821, 99993833, 99993841, 99993889, 99993893, 99993911, 99993917, 99993923, 99993947, 99993991, 99993997, 99994009, 99994021, 99994043, 99994061, 99994073, 99994079, 99994123, 99994129, 99994157, 99994177, 99994183, 99994201, 99994211, 99994229, 99994231, 99994253, 99994267, 99994273, 99994277, 99994309, 99994319, 99994327, 99994361, 99994373, 99994379, 99994471, 99994481, 99994553, 99994567, 99994571, 99994579, 99994607, 99994621, 99994633, 99994637, 99994669, 99994673, 99994679, 99994691, 99994703, 99994711, 99994723, 99994751, 99994759, 99994771, 99994801, 99994819, 99994849, 99994861, 99994877, 99994883, 99994907, 99994919, 99994963, 99995011, 99995039, 99995041, 99995059, 99995087, 99995111, 99995113, 99995171, 99995177, 99995197, 99995209, 99995213, 99995227, 99995249, 99995257, 99995261, 99995267, 99995279, 99995281, 99995297, 99995303, 99995317, 99995407, 99995417, 99995453, 99995507, 99995527, 99995549, 99995551, 99995563, 99995569, 99995573, 99995591, 99995603, 99995629, 99995641, 99995647, 99995663, 99995669, 99995671, 99995681, 99995699, 99995711, 99995723, 99995747, 99995767, 99995771, 99995783, 99995807, 99995813, 99995839, 99995851, 99995869, 99995891, 99995893, 99995899, 99995923, 99995933, 99995939, 99995957, 99995983, 99995999, 99996011, 99996059, 99996077, 99996079, 99996097, 99996121, 99996131, 99996133, 99996139, 99996151, 99996179, 99996181, 99996191, 99996229, 99996241, 99996251, 99996257, 99996271, 99996287, 99996293, 99996317, 99996343, 99996353, 99996389, 99996409, 99996419, 99996473, 99996509, 99996511, 99996517, 99996521, 99996551, 99996577, 99996583, 99996619, 99996647, 99996653, 99996667, 99996671, 99996679, 99996691, 99996697, 99996719, 99996749, 99996769, 99996779, 99996797, 99996803, 99996821, 99996833, 99996863, 99996899, 99996931, 99996947, 99996971, 99996983, 99997033, 99997063, 99997067, 99997069, 99997081, 99997127, 99997129, 99997151, 99997159, 99997187, 99997189, 99997243, 99997267, 99997357, 99997367, 99997369, 99997393, 99997411, 99997427, 99997441, 99997459, 99997493, 99997511, 99997523, 99997531, 99997543, 99997571, 99997609, 99997619, 99997649, 99997669, 99997679, 99997687, 99997691, 99997759, 99997769, 99997783, 99997789, 99997837, 99997841, 99997867, 99997871, 99997873, 99997879, 99997897, 99997901, 99997907, 99997913, 99997949, 99997957, 99997973, 99997981, 99998021, 99998051, 99998071, 99998099, 99998111, 99998147, 99998191, 99998207, 99998231, 99998251, 99998257, 99998291, 99998299, 99998323, 99998357, 99998363, 99998377, 99998413, 99998417, 99998429, 99998441, 99998447, 99998449, 99998473, 99998491, 99998497, 99998513, 99998543, 99998551, 99998557, 99998603, 99998609, 99998611, 99998663, 99998749, 99998783, 99998797, 99998819, 99998851, 99998869, 99998891, 99998909, 99998929, 99998933, 99998953, 99998971, 99998999, 99999043, 99999073, 99999077, 99999079, 99999089, 99999103, 99999113, 99999131, 99999157, 99999167, 99999187, 99999217, 99999247, 99999257, 99999259, 99999307, 99999323, 99999329, 99999343, 99999353, 99999373, 99999401, 99999437, 99999439, 99999481, 99999509, 99999517, 99999539, 99999541, 99999547, 99999551, 99999563, 99999587, 99999589, 99999611, 99999617, 99999623, 99999643, 99999677, 99999703, 99999721, 99999773, 99999787, 99999821, 99999827, 99999839, 99999847, 99999931, 99999941, 99999959, 99999971, 99999989, }; public void testSetUp() throws Exception { new Factorization02(); } public void testIsPrimeNumberByTable1() { Factorization02 f = new Factorization02(); for (int i = 1; i < 1000; i++) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_1_999, i) >= 0, f.isPrimeByTable(i)); } } public void testIsPrimeNumberByTable2() { Factorization02 f = new Factorization02(); for (int i = 99990001; i < 100000000; i += 2) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_99990001_99999999, i) >= 0, f.isPrimeByTable(i)); } } public void testIsPrimeNumberSimple1() { Factorization02 f = new Factorization02(); for (int i = 1; i < 1000; i++) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_1_999, i) >= 0, f.isPrimeNumberBySimple(i)); } } public void testIsPrimeNumberSimple2() { Factorization02 f = new Factorization02(); for (int i = 99990001; i < 100000000; i += 2) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_99990001_99999999, i) >= 0, f.isPrimeNumberBySimple(i)); } } public void testIsPrimeByRegex1() { Factorization02 f = new Factorization02(); for (int i = 1; i < 1000; i++) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_1_999, i) >= 0, f.isPrimeByRegex(i)); } } public void testIsPrimeByRegex2() { Factorization02 f = new Factorization02(); for (int i = 99990001; i < 100000000; i += 2) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_99990001_99999999, i) >= 0, f.isPrimeByRegex(i)); System.out.print(i + " "); System.out.flush(); } /* * java.lang.OutOfMemoryError: Java heap space */ } public void testIsPrimeNumberFermat1() { Factorization02 f = new Factorization02(); for (int i = 1; i < 1000; i++) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_1_999, i) >= 0, f.isPrimeNumberByFermat(i)); } } public void testIsPrimeNumberFermat2() { Factorization02 f = new Factorization02(); for (int i = 99990001; i < 100000000; i += 2) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_99990001_99999999, i) >= 0, f.isPrimeNumberByFermat(i)); } } public void testIsProbablePrimeByBigInteger1() { Factorization02 f = new Factorization02(); for (int i = 1; i < 1000; i++) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_1_999, i) >= 0, f.isProbablePrimeByBigInteger(i, 4)); } } public void testIsProbablePrimeByBigInteger2() { Factorization02 f = new Factorization02(); for (int i = 99990001; i < 100000000; i += 2) { assertEquals(Arrays.binarySearch(PRIME_NUMBERS_99990001_99999999, i) >= 0, f.isProbablePrimeByBigInteger(i, 4)); } } } ---
http://www8.ocn.ne.jp/~marimo/index.htm
駅から近い。昭和の香りのする雰囲気。
店内は広く、程よいくらいに暗い。ただ、節電のためか、音楽がなかったのが寂しかった。
順喫茶ではなく、喫茶・レストランなので、いろいろな定食系のメニューもある。
ホームページには書いていないが、デザート系も充実。
ケーキセットの中に、たこやきなんかもあるのには驚いた。
また、昔懐かしいプリンアラモード(\650)もあった。
ナポリタンのセットとプリンアラモード。
プリンアラモードは昔懐かしい。プリンもしっかりとした硬いプリン。
生クリームも昔懐かしい感じの味。
上にかかっているチョコチップも懐かしい感じかな。
店名になっている「まりも」だが、店内の真ん中くらいにいた。
また、店に入るときは気づかなかったが、店の前には鯉が泳いでいて、道を通る人がのぞいていた。