![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
perlでlog2を計算するにはどのようにしたらよいのでしょうか。
perldocによると
sub log2 {
my $n =shift;
return log($n)/log(2);
}
でよいはずですが、log2 が「正しく整数を返すかどうか」は保証されていないので、時として問題があるようです。
通常、log2 の結果 $a を単に print $a などとして出力する分には Perl が適当? に判断して丸め処理をしてる傾向があるようですが、これを
printf "%d", $a
とすると、本当に整数部だけが出力され、演算精度によっては意図
しない数値になる場合があるとのこと、計算機環境にインストール
した Perlで、演算精度を上げるオプションを追加した場合などで、実際に出力結果が異なる、との報告を受けました。
宜しくお願い致します。
No.2ベストアンサー
- 回答日時:
> このような数学的に正しい結果を求めておりますがいかがでしょうか
数学的に正しいなんていったら、コンピュータで計算させるのは
ある意味間違いです。
きちんと説明すると長くなるのでとても書ききれませんが、
通常、小数部を含む数字は一部の例外を除いてあくまで
「近似値」でしかありません。
ですので、
log[e](16)/ log[e](2)
自然対数だろうが常用対数だろうが、ある数値の
対数を取った時点で既に近似値に成り下がりますから、
ある程度の誤差が出るのはどうしようもありません。
誤差が出るのを見込んだ上で、補正するなりなんなり
する必要があります。
たとえば 2^1 ~ 2^53 までの log2 を質問にもある式で求めると
以下のようになります。
>perl -e "printf qq{%16.0f: %25.17f\n},2**$_,log(2**$_)/log(2) for
(1..53)"
2: 1.00000000000000000
4: 2.00000000000000000
8: 3.00000000000000000
16: 4.00000000000000000
32: 5.00000000000000000
64: 6.00000000000000000
128: 7.00000000000000000
256: 8.00000000000000000
512: 9.00000000000000000
1024: 10.00000000000000000
2048: 11.00000000000000000
4096: 12.00000000000000000
8192: 13.00000000000000000
16384: 14.00000000000000000
32768: 15.00000000000000000
65536: 16.00000000000000000
131072: 17.00000000000000000
262144: 18.00000000000000000
524288: 19.00000000000000000
1048576: 20.00000000000000000
2097152: 21.00000000000000000
4194304: 22.00000000000000000
8388608: 23.00000000000000000
16777216: 24.00000000000000000
33554432: 25.00000000000000000
67108864: 26.00000000000000000
134217728: 27.00000000000000000
268435456: 28.00000000000000000
536870912: 29.00000000000000400
1073741824: 30.00000000000000000
2147483648: 31.00000000000000400
4294967296: 32.00000000000000000
8589934592: 33.00000000000000000
17179869184: 34.00000000000000000
34359738368: 35.00000000000000000
68719476736: 36.00000000000000000
137438953472: 37.00000000000000000
274877906944: 38.00000000000000000
549755813888: 39.00000000000000700
1099511627776: 40.00000000000000000
2199023255552: 41.00000000000000000
4398046511104: 42.00000000000000000
8796093022208: 43.00000000000000000
17592186044416: 44.00000000000000000
35184372088832: 45.00000000000000000
70368744177664: 46.00000000000000000
140737488355328: 47.00000000000000700
281474976710656: 48.00000000000000000
562949953421312: 49.00000000000000000
1125899906842624: 50.00000000000000000
2251799813685248: 51.00000000000000700
4503599627370496: 52.00000000000000000
9007199254740992: 53.00000000000000000
ところどころ全部ゼロであるはずの小数部に
ゼロ以外の数字が登場しています。
log(2)の精度を上げるなどすればもっと小数部の
深いところで出るようにはできますが、
根本的にはやり方をまるきり変えないと解決できませんし、
2のべきの数字なら求めるのはある意味簡単ですが、
どのような入力に対しても「数学的に正しい値」というのは
無理でしょう。
有理数演算とか記号処理とかやればそれなりに正確さは求められるでしょうけど。
参考情報として、
Perlではありませんが
Binary logarithm - Wikipedia, the free encyclopedia
http://en.wikipedia.org/wiki/Binary_logarithm
にもうちょっと頑張ってlog2の値を求めているやり方があります。
チェックを忘れてしまっており、お礼が遅れまして大変失礼しました。数学的正しさは無理であることがわかりました。
2進数化し、桁数の算数を行うことで対応しました。
No.3
- 回答日時:
$n が 2 のべきのときだけを考えるなら, ハッシュを使えばいいんでしょうねぇ.
my %log2 = map { 2**$_, $_ } 0..52;
とか (52 は適当に変えてください).
そうじゃない ($n として 2 のべき以外の値も必要) と, 2 を底とする対数の値が超越数になるので「数学的に正確」な値を小数で表現するのは不可能です.
チェックを忘れてしまっており、お礼が遅れまして大変失礼しました。数学的正しさは無理なので、2進数になおして、桁数でチェックするなどの方法でプログラムを作成することで対応しました。
No.1
- 回答日時:
括弧をつけて正確、というのを強調されてますが、
log(2) とか log($n) という計算をした時点で
すでに近似値でしかないのですが、さらにその近似値を二つ使って
計算した値でどんな「正確さ」を求めているのでしょうか?
> 演算精度を上げるオプションを追加した場合などで、実際に出力結果が異なる、
そりゃあ結局近似値なんですから、精度を変えれば
値(の末尾の方)が変わるのは当たり前じゃないですか?
> log2 が「正しく整数を返すかどうか
というのが問題なら、
> log($n)/log(2);
を
int(log($n)/log(2));
とするとか。
で、質問者さんが本当にやりたいこと、最終的な解決を求めている
ことがらとはどんなことなのでしょうか?
この回答への補足
お世話になります。宜しくお願い致します。質問は言葉足らずでした。「正確」とは数学的正確さです。
例えば $nが16であるとした場合、
log[e](16)/ log[e](2)
=log[2](16) = 4となりますが、これを指しています。
このような数学的に正しい結果を求めておりますがいかがでしょうか。宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 化学 化学が得意な方に質問です。この問題の正解を教えて欲しいです。 【問題1】Log Kowの記述について 1 2022/09/26 23:44
- 数学 図はn=8の場合だけど、3段(=log[2]8)のバタフライ (3回の計算)で処理してる。と言われた 4 2022/03/24 19:41
- 数学 極限の計算をお願いします。 {log(2x+3)}/{log(3x+1)} のx→∞の極限値の求め方 3 2022/08/03 20:58
- 数学 不定積分の初歩 1 2022/09/25 00:11
- 数学 数学2で学ぶ対数のlogの計算に関しての質問です。 (log2-log3)-(log1-log2)= 4 2022/06/17 11:37
- 統計学 統計検定2級を取ろうと勉強中なのですが分からないことがあったので質問させていただきます。 スタージェ 6 2023/01/01 23:02
- C言語・C++・C# C言語 3 2022/10/04 15:07
- 数学 統計学の問題について教えて下さい。高校数学 大学数学 5 2023/03/07 09:04
- 数学 回答者どもがなかなか答えられないようなので、考えてみました。 ∫[0,π/2]log(sinx)/( 4 2022/08/31 16:30
- 大学・短大 効用関数の微分の計算について 1 2022/06/05 11:07
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
sprintfについて
-
perlのpushについてです。
-
perlでの文字列抽出
-
重複するデータを抽出できる秀...
-
教えて!perlから.exeファイル...
-
エクセルVBAで素数だけを出力す...
-
コンソール出力をテキストに出...
-
sprintfで10進数を桁数指定で16...
-
文章を一文一文として処理する...
-
オーバーラップ計算法について
-
python renameについて
-
FindFirstFileとFindNextFileで...
-
VBAでCSVファイルの特定行を書...
-
batファイルでrenameができませ...
-
VBAでCSVファイルを途中行まで...
-
Perlでのファイル出力における...
-
ListBoxのデータを高速でファイ...
-
fgets で値が取得できない
-
Pythonでegrep機能をつかいたい
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
awkスクリプトでダブルクォーテ...
-
DOSコマンドで、標準出力を出力...
-
sprintfについて
-
エクセルVBAで素数だけを出力す...
-
C言語の問題について
-
Perl<->Oracle間での文字化けに...
-
log2の「正確な」計算方法
-
教えて!perlから.exeファイル...
-
重複するデータを抽出できる秀...
-
Perlでファイルの末尾から指定...
-
CGIから外部コマンド実行時の標...
-
ファイル出力の改行コードをLFに
-
至急お願いします。C言語で.img...
-
LWPでPOST送信した後に送信先に...
-
perlでcsvの出力について
-
バッチファイルで、記号を含む...
-
Perl 内で実行される Perl が S...
-
文字コードの変換(Shift-JISか...
-
Perlでエラーログに日時をつける
-
Active Perl の動作異常について
おすすめ情報