Arduinoを使って1602LCDで高速素数表示をした
素数を数えると精神衛生上によいと聞いたので、
LCDキャラクタディスプレイに素数を表示して冷静になろうと思う。
リンク先にあるミラーラビン素数判定法というものを、そのまま実装した。
結果が合っているかの確認はしていないけど、落ち着く可能性はあると思う。
IDEのバージョンは0022で
ボードは"Arduino Pro or Pro Mini (3.3V,8MHz)w/ATmega168"を使用した。
以下ソース
// 高速素数表示、時間付 #include <stdint.h> #include <stdio.h> #include <LiquidCrystal.h> LiquidCrystal lcd(12, 11, 10, 5, 4, 3, 2); void setup() { randomSeed(analogRead(0)); lcd.begin(16, 2); lcd.clear(); lcd.setCursor(0, 0); } uintmax_t num = 100000UL; // 最初に判定したい数 uint32_t time; char str[20]; void loop() { if (isPrime(num)) { time = millis(); snprintf(str, sizeof(str), "PrimeNum:%7lu", num); lcd.setCursor(0, 0); lcd.print(str); snprintf(str, sizeof(str), " %02luh%02lum%02lus%03lums", time / 1000UL / 3600UL % 24UL, time / 1000UL / 60UL % 60UL, time / 1000UL % 60UL, time % 1000UL); lcd.setCursor(0, 1); lcd.print(str); } num++; } // ミラー・ラビン素数判定法 wikipediaから引用・改変 bool isPrime(const uintmax_t n) { if (n == 2) { return true; } if (n == 1 || (n & 1) == 0) { return false; } uintmax_t d = n - 1; while ((d & 1) == 0) { d >>= 1; } uintmax_t a, t, y; for (int i = 0; i < 20; i++) { a = random(1, n-1); t = d; y = pow(a, t, n); while (t != n-1 && y != 1 && y != n-1) { y = (y * y) % n; t <<= 1; } if (y != n-1 && (t & 1) == 0) { return false; } } return true; } uintmax_t pow(uintmax_t base, uintmax_t power, const uintmax_t mod) { uintmax_t result = 1; while (power > 0) { if ((power & 1) == 1) { result = (result * base) % mod; } base = (base * base) % mod; power >>= 1; } return result; }
写真か動画取ればよかった。