ぎるばーとのノート

もっともっと遠くへ行きたい 空が広く見える場所まで

罠が潜んでいる!

 ワンライナーの陥穽。

 剰余(n rem m)演算とモジュロ(n mod m)演算はnが負のとき結果が違ってきます。端的に言うとモジュロ演算で結果が負の数になることはありません。(詳細は英語版ウィキペディアモジュロ演算。)
 例を挙げた方がいいか……。

n -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4
rem 3 -1 0 -2 -1 0 -2 -1 0 1 2 0 1
mod 3 2 0 1 2 0 1 2 0 1 2 0 1

 C言語Javaの%演算子は剰余演算なので、モジュロ演算の方は(必要なら)自分で書くことになります。

public static int mod(int n, int m) {
    if (m <= 0) {
        throw new ArithmeticException();
    }
    int rem = n % m;
    if (n < 0) {
        return rem + m;
    }
    else {
        return rem;
    }
}

 一部ではif文抜きでモジュロ演算する裏技(?)として、

(n % m + m) % m

が紹介されています。が、これは途中で足し算がオーバーフローすると悲惨なことになるので避けましょう。

    int m = Integer.MAX_VALUE;
    System.out.println(mod(10, m));
    System.out.println((10 % m + m) % m);
10
-2147483639

 一見よさそうに見えて罠が潜んでいる、という話でした。了。

log2(x)

 JavaのMathクラスにはlog2(x)関数が見当たりません。
 他のプログラミング言語でもlog2(x)がない場合には役立つ話かも……?

 さて、下のやり方で何か問題があるでしょうか?

Math.log(x) / Math.log(2)

 対数の底の変換は、
\log_a x = \frac{\log x}{\log a} = (\log_a e) \log x
なので数学的には自然というか素朴な方法ですね。

 しかし、浮動小数点演算では予想外の結果になってしまうことがあります。

    System.out.println(Math.log(1 << 29) / Math.log(2));
29.000000000000004

 xがぴったり2のn乗なら、正確にnを返してほしいと思いませんか?(思わなければ続きは読まなくて大丈夫です。)
 かといって2のn乗を特別扱いすると、単調性(a \le bならばf(a) \le f(b))が保たれるか分からないので、それはそれでうーんな感じです。
 ということで、なるべく誤差を発生させない計算方法を考えます。

 まず、
x = s \times 2^k
と表します。(kは整数で、sの範囲を制限すると決まる。)
\log_2 x = \log_2 s + k
 ここで、\log_2 sの絶対値が小さいとき、浮動小数点数の性質(0に近いほど細かく値の区別ができる)から誤差も小さく計算できます。

 ここではsの範囲を、
\cases{0.5 \le s < 1 & \text{($x < 1$)}\\ 1 \le s < 2 & \text{($x \ge 1$)}}
とします。(絶対にこうすべきというわけでもない。)
 あとは非正規化数に注意しつつコード化すると次のようになります。

public static double log2(double x) {
    // 特殊な値
    if (Double.isNaN(x) || x < 0.0) return Double.NaN;
    if (x == Double.POSITIVE_INFINITY) return Double.POSITIVE_INFINITY;
    if (x == 0.0) return Double.NEGATIVE_INFINITY;
    // ここから
    int k = Math.getExponent(x);
    if (k < Double.MIN_EXPONENT) {
        // 非正規化数は取扱い注意!
        k = Math.getExponent(x * 0x1.0p52) - 52;
    }
    if (k < 0) {
        k++;
    }
    double s = Math.scalb(x, -k);
    final double LOG2_E = 1.4426950408889634;
    return k + LOG2_E * Math.log(s);
}

 比較テスト。(x = 2^n;\ n = -1074, \ldots, 1023

    int j = 0, k = 0;
    for (int i = -1074; i <= 1023; i++) {
        double x = Math.scalb(1.0, i);
        if (log2(x) != i) j++;
        if (Math.log(x) / Math.log(2) != i) k++;
    }
    System.out.println("log2(x) function errors: " + j);
    System.out.println("Math.log(x) / Math.log(2) errors: " + k);
log2(x) function errors: 0
Math.log(x) / Math.log(2) errors: 441

 ライブラリでも作るのでなければこれで十分かと……。

魔王も現れない

 おお、放置もいいところだ。そろそろ再開していきたいなー。

 以前と方向性をチェンジしてみようと思っています。プログラミング関連の記事とか、基本的なアルゴリズムの解説なんかをやっていこうかと。

 このところ、ちょっと、体調や精神自体は改善しつつもぶっ倒れている時間が多くなって……。行動範囲は着々と広がってきているのですが、行動時間はむしろ狭まっている状況です。
 倒れているというのは、度を超えた満腹状態(主観的に腹十六分目くらい?)で目が回って動けないという感じ。食べ過ぎてるつもりはないけれど、これが今の自分なので仕方ないと思っています。

 PCの前で長時間何かを書くというのが辛いので、短い時間でさらっと書ける軽い話が中心になるはずです。
 以上、最近更新していなかった言い訳と再開宣言でした。これからまたよろしく!

ビフィズス菌と乳酸菌

 腸内環境を改善して健康を取り戻そう、ってな話です。
 近頃はプロバイオティクスという言葉も一般化してきて、スーパーの売り場やCMでも見かけるようになりました。(それだけお腹のトラブルに見舞われている人が多いのでしょう……。)

 半年ほど実践してみて、正直に言うと過敏性腸症候群の症状がなくなったわけではないです。残念ながら。。
 とはいえ、はっきり実感が持てるくらい日々の生活の質が向上しました!
 「ああ、QOLってこういうことかー。」なんて思ったりも……。
 同じ病気やお腹の症状で悩まれている方は、(まずは病院へ行って)一度試されることをおすすめします!

 以下、ビフィズス菌&乳酸菌関連のメモ。

ビフィズス菌とは

 Bifidobacterium属の細菌。
 ヒトや動物の腸内に棲む善玉菌で、腸内の細菌環境を整える。
 糖を分解して乳酸と酢酸を生成する。乳酸菌に含めたり含めなかったり。

  • ビフィダム菌(Bifidobacterium bifidum
    • ビオフェルミンS(G9-1株)→参考
      主に大腸にすみつき、乳酸と酢酸をつくり、整腸効果をたかめます。
  • ブレーベ菌(Bifidobacterium breve
    • ミルミル(ヤクルト株)→パッケージに記載
  • ロンガム菌(Bifidobacterium longum
    • 森永ビヒダス(BB536株)→パッケージに記載
    • ナチュレ恵(ビフィズス菌SP株)
  • Bifidobacterium animalis subsp. lactis
乳酸菌とは

 糖を分解して乳酸を生成する細菌をひっくるめてこう呼ぶ。
 乳酸は腸の内容物を弱酸性に保ち、悪玉菌の増殖を抑える効果がある。

  • フェーカリス菌(Enterococcus faecalis
    • ビオフェルミンS(129 BIO 3B株)→参考
      主に小腸にすみつき、すばやく増えて乱れた腸内菌叢を整えます。
  • アシドフィルス菌Lactobacillus acidophilus
    • ビオフェルミンS(KS-13株)→参考
      主に小腸にすみつき、乳酸を多くつくり、有害菌を抑えます。
    • ミルミル→パッケージに記載
  • ガセリ菌(Lactobacillus gasseri
    • ナチュレ恵(ガセリ菌SP株)→参考
  • カゼイ菌(Lactobacillus casei
  • ブルガリクス菌(Lactobacillus delbrueckii subsp. bulgaricus
    サーモフィルス菌(Streptococcus thermophilus
有胞子性乳酸菌とは

 胞子を作るタイプの乳酸菌。
 胃酸や熱に強い胞子の状態で腸まで達して、発芽・増殖を始める。

  • Bacillus coagulans
    • パンラクミン(ラクボン菌)
      乳酸菌の胞子を製剤化したもので、安定性がよく、服用後は腸管内で繁殖して腐敗菌などの有害細菌の繁殖を抑えて、整腸作用を発揮します
    • ビスコ(スポロ乳酸菌)→参考

食事&体調記録カレンダー

食事&体調記録カレンダー

 なんか定期的にこういうものを作りたくなります。
 自分用なので汎用性は疑問あり。食事と体調を記録してお医者さんに伝えたりするのに便利かもしれません。
 食生活を見つめ直すと、体調不良の原因が見つかることもあります。(例:脂っこいものを食べると次の日しんどい→肝臓・胆嚢・膵臓の働きが弱っている?)

 失ってはじめて分かる健康のありがたさ……!