- ベストアンサー
16進変換で不具合
- 値を10進、16進の相互変換を行いたいのですがうまく行かずに困っています。小さな桁数なら実現できているのですが、大きくすると変になります。
- 10進→16進は作成することができましたが、16進→10進にする際にうまくいかない問題が発生しています。
- 足し算の結果が期待と異なる現象が発生しており、手計算やExcelでの検算でも解決策が見つかっていません。お手数ですが、助けていただけないでしょうか?
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>This is perl, v5.8.5 built for sun4-solaris Excelで検算したとかあったのでWindows用のPerlだと思ってたのですが Sparc Solarisのでしたか。 であれば、CPUの違いによる可能性もあるのでもし可能なら Windowsのか、あるいは別のOS(x86用のものがたぶん望ましい)のもので 確かめられるのならやってみてください。 あと、bigintつかってても出力に pritnf使うとまずいです。たぶん。 bigint自体の文字列化のメソッドを使ってどうにかしてください。
その他の回答 (5)
- azicyan
- ベストアンサー率21% (368/1747)
sakusaker7さま > 今、5.8.8でも試してみましたが5.10.0のときと結果は同じでしたよ? うう。何ででしょうか・・・ > 要は前回の回答でちょっと書いたように、本来15~6桁分しか正しく保持できないところに > 10000081000008099840 という20桁の数値を食わせているからです。 BigIntを使っているのにダメなんでしょうか。 それともそもそも使い方が間違っていますでしょうか・・・ 最後の足し算だけがおかしい感じなので、 10桁ずつ分けて計算して文字列として連結してしまえば 出来ることは出来るんですよね・・・ でもなんとなくwindows標準の電卓でも出来ることが 出来ないことに違和感を感じます。 >>sakusaker7さまの16進変換のアルゴリズムが私には理解できませんでした(恥 >そんなに小難しいことをやっているわけではないのですが(^^; > こっちも説明が必要ですか? 下位の桁から 16の0乗 * 1の位 16の1乗 * 10の位 ・ ・ とやる方法しか知らなかったので、うーんどうやってるんだろう・・・と思いました。 あ、でも、またそれはよく勉強してみます! いまは20桁の足し算が出来ない・・・って言うのをまずはナントカしたいです。 perlのバージョンを書いておきます。 ######################################## perl -version This is perl, v5.8.5 built for sun4-solaris Copyright 1987-2004, Larry Wall Perl may be copied only under the terms of either the Artistic License or the GNU General Public License, which may be found in the Perl 5 source kit. Complete documentation for Perl, including FAQ lists, should be found on this system using `man perl' or `perldoc perl'. If you have access to the Internet, point your browser at http://www.perl.com/, the Perl Home Page. ########################################
- sakusaker7
- ベストアンサー率62% (800/1280)
今、5.8.8でも試してみましたが5.10.0のときと結果は同じでしたよ? #use feature の行は削らないとダメですが、use warnings は #5.8.8でも使えるはずなんですが… で、質問者さんの計算結果と比べてみると 39062816406281640 625005062500506240 ← ここまでは同じ 10000081000008099840 ← でもここで160食い違いが ということになってますね。 たぶん、 8AC76CAFD29DA8A0 の下から二桁目の'A'を別の数字に変えると、誤差はそれに応じて変わると思います。 要は前回の回答でちょっと書いたように、本来15~6桁分しか正しく保持できないところに 10000081000008099840 という20桁の数値を食わせているからです。 詳しい説明は今はちょっと書いている余裕がないので割愛。 #時間をくれれば書きますけど >sakusaker7さまの16進変換のアルゴリズムが私には理解できませんでした(恥 そんなに小難しいことをやっているわけではないのですが(^^; こっちも説明が必要ですか?
- azicyan
- ベストアンサー率21% (368/1747)
sakusaker7さま、実は質問者です (昨晩どうしても質問したかったのになぜかこのIDでログインが出来なくなり 急遽新規のIDで質問した次第です・・・) さて、教えてもらったコードを試したところ・・・なぜか違う結果になりました。 5.8だと結果が違ってしまうようですね。 ちなみに use warnings; use feature ':5.10'; の2行が、そんなのない、といわれてしまうのでコメントにしました。 8 138 2220 35527 568438 9095020 145520330 2328325295 37253204733 596051275730 9536820411689 152589126587037 2441426025392602 39062816406281640 625005062500506240 10000081000008099840 なぜか160足りない!(汗 実は既にBigIntは使っているのですが・・・何かがおかしいです。 sakusaker7さまの16進変換のアルゴリズムが私には理解できませんでした(恥 なので、オーソドックスにこんな感じにしてみました。 (変数超適当です。すみません) #!/usr/local/bin/perl use bigint; my $hexstr = "8AC76CAFD29DA8A0"; my $i=0; my $hoge=0; foreach $b (reverse (split (//,$hexstr))){ $c=hex $b; $test=$c * 16 ** $i; print qq($b($c) * 16 ** $i =\n); printf qq(%25.0f\n) ,$test; $i++; $hoge+=$test; } printf "%25.0f\n", $hoge; <実行> 0(0) * 16 ** 0 = 0 A(10) * 16 ** 1 = 160 8(8) * 16 ** 2 = 2048 A(10) * 16 ** 3 = 40960 D(13) * 16 ** 4 = 851968 9(9) * 16 ** 5 = 9437184 2(2) * 16 ** 6 = 33554432 D(13) * 16 ** 7 = 3489660928 F(15) * 16 ** 8 = 64424509440 A(10) * 16 ** 9 = 687194767360 C(12) * 16 ** 10 = 13194139533312 6(6) * 16 ** 11 = 105553116266496 7(7) * 16 ** 12 = 1970324836974592 C(12) * 16 ** 13 = 54043195528445952 A(10) * 16 ** 14 = 720575940379279360 8(8) * 16 ** 15 = 9223372036854775808 10000081000008099840 あああああ!!!やっぱり160どこかに行ってしまいます。 で、ココで気を取り直して、上の計算結果を1の位、10の位、100の位と 計算してみたところ・・・ 1の位・・・50 10の位・・・75 100の位・・・72 となり、どうやら、途中の桁ごとの計算はあっているようなのです。 50 75 72 -------- 8000 (100の位までの計算結果。少なくとも10の位が4ではないはず。) 合計の計算がおかしいみたいです・・・
- sakusaker7
- ベストアンサー率62% (800/1280)
桁が大きすぎますね。 もうちょっと小さい数字で試すといいと思います。 #!/usr/bin/perl use strict; use warnings; use feature ':5.10'; my $hexstr = "8AC76CAFD29DA8A0"; my $acc = 0; foreach my $digit (split q{}, $hexstr) { #say $digit; $acc = $acc * 16 + hex $digit; #say $acc; printf "%21.0f\n", $acc; } 8 138 2220 35527 568438 9095020 145520330 2328325295 37253204733 596051275730 9536820411689 152589126587037 2441426025392602 39062816406281640 625005062500506240 10000081000008100000 “たまたま”正しい数字が出ていますが、精度としては15~16桁分しかないので 変換のやり方しだいで質問者さんのようにおかしな結果になることがあります。 んでまあ bigint とか使えばいいと思います。はい。
- sakusaker7
- ベストアンサー率62% (800/1280)
差し支えなければ変換(両方向とも)のコードを見せてもらえますか? たぶんオーバーフローしているんだと思います。