繰り返し文における小数の挙動

このQ&Aのポイント
  • 繰り返し文で小数を操作する際に、表示がおかしくなる現象が発生しています。
  • 具体的には、0.001ずつ増加する変数に途中から0.000000000001が加わってしまいます。
  • この挙動を止める方法や原因について教えていただけないでしょうか。
回答を見る
  • ベストアンサー

繰り返し文における小数の挙動

以下のような簡単なプログラムを書いて実行させたところ、小数点表示の挙動がおかしくなりました。 ###プログラム ここから #!/usr/bin/perl use strict; use warnings; for(my $i=0.01;$i<=1;$i+=0.001) { print $i,"\n"; } ###ここまで ##結果 ここから . . . 0.685 0.686 0.687 0.688000000000001 0.689000000000001 0.690000000000001 ##ここまで 以上のように、0.001づつ増加する $i に途中から000000000001が加わってしまいます。この000000000001が足される現象をやめさせたいです。原因、解決策等おわかりであれば教えていただけないでしょうか。よろしくお願いします。

  • Perl
  • 回答数1
  • ありがとう数1

質問者が選んだベストアンサー

  • ベストアンサー
  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

>原因、解決策等おわかりであれば 「浮動小数点 誤差」で検索して下さい。 今回の場合、増分が0.001なので…… 1000倍の下駄を履かせて扱う。って方法があるかと。 「固定小数点 下駄」辺りで検索して下さい。

Murata0715
質問者

お礼

ご返信ありがとうございました。調べてみました。 ・コンピューターの実際の計算では、2進法を使っているので小数点を扱う際に不都合が出てくる場合がある。 ・そこで、整数にて繰り返し文を行い、誤差の蓄積を防ぐ。 以上のような理解であっているでしょうか。これを踏まえてプログラムを書き換えると以下のようになりますが、確かにこれでうまくいきました。ありがとうございました。 for(my $i=10;$i<=1000;$i+=1) { print $i/1000,"\n"; } しかし、ここでもう一つ疑問が浮かぶのですが、確かにこの「浮動小数点」に関するウェブページはたくさん存在しているものの、小数の代わりに一旦整数を用いるような以上の手法は日常的にプログラミングをされているプログラマーの方も一般的に用いる手法なのでしょうか。

関連するQ&A

  • use strictが効かない (PERL)

    たびたびお世話になっております。 PERL version 5.14.2 をWindows 7 のコマンドプロンプトから起動して使っています。 use strict; と一行目に書くと 宣言されていない変数があれば拒絶されるとのことで #!/usr/bin/perl use strict; use warnings; $a = 10; print "$a\n"; というスクリプトを書きました。が、すんなり動いてしまいます。 use strict; は どうすればうまく効くのでしょうか。 ご指導お願いします。

    • ベストアンサー
    • Perl
  • perl ハッシュ エラー

    現在perlの勉強中で、ハッシュの項目まできました。しかし、use strictにするとこのコードがエラーになります。 #!/usr/bin/perl use strict; use warnings; print "Content-type:text/html\n\n"; $hoge{"key1"} = "value1"; print $hoge{"key1"}; exit; ヴァージョンは5.8.9です。use strictをコメントアウトすればエラーはでません。どうしてエラーになってしまうのでしょうか?どうすればエラーを出さずに表示することができるのでしょうか?どうかご教授ください。よろしくお願いします。

    • ベストアンサー
    • Perl
  • 正規表現の書き方に困っております。

    あるSQLのダンプを変換するプログラムをPerlで書いているのですが、 うまく正規表現が書けなくて困っております。 データの途中に,が有ると、うまくいきません。 ''の中に囲まれた,は無視するという正規表現を書きたいのです。 また、'''B'も正しく処理できれば、完璧です。 #!/usr/bin/perl use strict; use warnings; #my $a = qq{'A','B',1}; --> うまくいく  ['A']['B'][1] #my $a = qq{'A,','B',1}; --> うまくいかない ['A] ['] ['] my $a = qq{',','''B',1}; --> もっとうまくいかない ['][']['] if($a =~ /(.+?),(.+?),(.+?)/){ print "[$1]\n"; print "[$2]\n"; print "[$3]\n"; }else{ print "ERR!\n"; } exit; __END__

    • ベストアンサー
    • Perl
  • サーバーエラーについて

    次のプログラムを入力してみました #!/usr/bin/perl use strict; use warnings; print "Content-type: text/html\n\n”; print "Hello World!"; 実行したらInternal Sever Errorが表示されました。 プロバイダのアップロードするときのホームページサーバがwww7a.biglobe.ne.jpからftps.biglobe.ne.jpに変更しました。

    • ベストアンサー
    • Perl
  • perlで配列名を動的に作り出したい

    試しに次のようにしてみましたがエラーになりました。 #!/usr/local/bin/perl use strict; use warnings; my $mystr = "abcde"; my @{$mystr} = (1,2,3); $mystrの内容はいろい変わっていきます。 ご存知の方いらっしゃいましたらすみませんが教えてください。 よろしくお願いいたします。

    • ベストアンサー
    • Perl
  • SSIの表示

    perl/cgiの勉強中でssiでhtmlへの埋め込みを行いたいのですが、何故か出力が2度されてしまいます。 以下実行プログラムと結果です。 [test.cgi] #!/usr/bin/perl -w use strict; use warnings; print "Content-type:text/html\n\n"; print "hoge"; exit; [test.shtml] <html> <head></head> <body> <!--#include virtual="/cgi-bin/test.cgi"--> </body> </html> [出力] hogehoge …となってしまいます。どなたかご教示願えませんでしょうか? よろしくお願いいたします。

    • 締切済み
    • CGI
  • 浮動小数点演算でのエラー

    下記のようなスクリプトを実行したところ 計算結果がうまく表現されてません。 ####スクリプトの中身(tmp.plx)#### #!/usr/local/bin/perl -w use strict ; my $x = 38.475 ; foreach ( 0..21 ){ $x += 0.495 ; print $x . "\n" ; } ####実行結果#### tmp.plx 38.97 39.465 39.96 40.455 40.95 41.445 41.94 42.435 42.93 43.425 43.92 44.415 44.91 45.405 45.9 46.395 46.89 47.385 47.88 48.375 48.8699999999999 #<=ここで本来48.87 49.3649999999999 #######ここまで 期待値が48.87と出て欲しいところ 上記のような結果となります。 2進数での計算が浮動小数点を完全に表現することができない ことはわかるのですが、 $a=48.375; $a+=+0.495 ; print $a . "\n" ; # 48.87を表示 と単体での計算が正しい結果が出るのが理解できません。 どうしてなのでしょうか?

    • ベストアンサー
    • Perl
  • perlのDigest::MD5;でのMD5算出が異なる

    perlのDigest::MD5;でのMD5算出が異なる 下記、スクリプトをレンタルサーバ上と、WindowsOS上で走らせてみたところ、おなじファイルにも関わらず、MD5が異なります。 何故でしょうか? #!/usr/local/bin/perl use strict; use warnings; use Digest::MD5; my $file = 'test.zip'; my $ctx = Digest::MD5->new; open my $fh, "<$file"; $ctx->addfile($fh); my $md5 = $ctx->hexdigest; close($fh); open my $fh2, ">>md5.txt"; print $fh2 "$file $md5\n"; print "$file $md5\n"; close $fh2;

    • ベストアンサー
    • Perl
  • プロトタイプ宣言のワーニングについて

    関数のプロトタイプ宣言と、それに関するwarningsプラグマについてお教えください。 関数のプロトタイプ宣言は、その関数を呼び出す側がコンパイルされる時点で、すでに存在する必要があり、また、use warningsによってプラグマを有効にしておくと、遅いプロトタイプ宣言について警告してくれると理解していました。 以下の2例は、どちらもプロトタイプ宣言が遅いために、うまくプロトタイプが働かない例です。 しかし、(例1)ではwarningが表示されるのに対し、(例2)では表示されません。 どこか私の理解が誤っているのかと思うのですが、このようになる理由についてご教授いただきたく、よろしくお願いいたします。 ■ (例1) #!/usr/bin/env perl # -*- mode: cperl; coding:utf-8 -*- use strict; use warnings; my @a= 1..4; mypush( @a, 5..8); print join( ",", @_), "\n"; sub mypush(@@){ if( @_== 2){ print "ok.\n"; }else{ print "Prototypes does not work, arg. num=", 0+ @_, "\n"; } } □(出力1) main::mypush() called too early to check prototype at ./chk_prototype.pl line 10. Prototypes does not work, arg. num=8 ■(例2) #!/usr/bin/env perl # -*- mode: cperl; coding:utf-8 -*- use strict; use warnings; test_2(); exit 0; sub test_2{ my @a= 1..4; mypush( @a, 5..8); print join( ",", @_), "\n"; } exit 0; sub mypush(@@){ if( @_== 2){ print "ok.\n"; }else{ print "Prototypes does not work, arg. num=", 0+ @_, "\n"; } } □(出力2) Prototypes does not work, arg. num=8 ---- なお、Perlは、 perl -v This is perl, v5.10.1 (*) built for x86_64-linux-thread-multi を使用しております。

  • for文の中でエラーが出てしまいます。

    Perl初心者で、1から勉強始めました。 質問ですが、 #!c:\perl\bin\perl -w use strict; print "Content-type: text/html\n\n"; my %data1 = ( 'id','ID001', 'name','たなか', 'birthday','1970/10/10' ); my %data2 = ( 'id','ID002', 'name','すずき', 'birthday','1972/03/21' ); my %person = (\%data1,\%data2); for (my $i=0; $i<@person; $i++) { my %row = %{$person[$i]}; print "$row{'id'}:$row{'name'}($row{'birthday'}生)<br>\n"; } テキスト通りにやっているつもりですが、のforの中でエラーが出てしまいます。見直してもどこが悪いか分かりません。誰かお暇な方教えてください。お願いします。

    • ベストアンサー
    • Perl

専門家に質問してみよう