質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1635閲覧

While文が正しく計算されない

hirororo

総合スコア72

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2017/02/08 16:25

編集2017/02/08 16:58

いつもこちらのサイトではお世話になっております。

phpで作る計算ツールについて、1つ質問させて下さい。

以下のコードで、While文を使って計算すると正しく計算されません。

直接、$bに数字を入れると正しく計算されます。

以下のコードで間違いがあったらお教えください。

どうぞよろしくお願い申し上げます。

<?php $a = 600; $d = 100; $b=0.01; while($b<=1){ $c=$a/$b; $cc=intval($c); $e=$d+$cc; $x=($e/$cc)*$d; $f=$x+$e; $twr=$f/$cc; $b+=0.01; echo "$twr"; } ?>

■試してみたこと
・$bに数字の1を代入→正しく計算される。
・$bに数字の0.01を代入→繰り返し処理はされるが間違った答えが算出される。

・$b+=0.01;の直下にecho "$b";で出力→
While文で正しく0.01ずつ増えるが、$twrが正しく算出されない。

・「$aと$dは本来、POSTにより数値の状態で受け取る」

■環境
レンタルサーバー(ロリポップ)に、phpファイルをアップし、ブラウザで閲覧する形で、ツールを作っております。

■追加情報

・「$aと$dは本来、POSTにより数値の状態で受け取る」

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kei344

2017/02/08 16:47

質問文のコードはコードブロックで囲んでいただけませんか? ```(バッククオート3つ)で囲み、前後に改行をいれるか、コードを選択して「<code>」ボタンを押すとコードブロックになります。
hirororo

2017/02/08 16:59

ご指摘ありがとうございます。コードに```を追加致しました。
guest

回答2

0

ベストアンサー

BC Math 関数 を使えばよいのでは。

【PHP: 浮動小数点数 - Manual】
http://php.net/manual/ja/language.types.float.php

警告
浮動小数点数の精度

浮動小数点数の精度は有限です。 システムに依存しますが、PHP は通常 IEEE 754 倍精度フォーマットを使います。 この形式は、1.11e-16 のオーダーでの丸め処理で誤差が発生します。 複雑な算術演算をすると、誤差はさらに大きくなるでしょう。そしてもちろん、 いくつかの演算を組み合わせる場合にも誤差を考慮しなければなりません。

さらに、十進数では正確な小数で表せる有理数、たとえば 0.1 や 0.7 は、 二進数の浮動小数点数としては正確に表現できません。 これは、仮数部をいくら大きくしても同じです。 したがって、それを内部的な二進数表現に変換する際には、どうしても多少精度が落ちてしまいます。 その結果、不思議な結果を引き起こすことがあります。たとえば、 floor((0.1+0.7)*10) の結果はたいてい 7 となるでしょう。おそらくは 8 を想定していらっしゃるでしょうが、そのようにはなりません。 これは、(この計算結果の) 内部的な値が 7.9999999999999991118... のようになっているからです。

よって、小数の最後の桁を信用してはいけませんし、 小数を直接比較して等しいかどうかを調べてはいけません。より高い精度が必要な場合には、 任意精度数学関数または gmp 関数を代わりに使用してください。

【[PHP]PHPで小数計算する? | マリンロード】
https://www.marineroad.com/staff-blog/7878.html

【小数点計算での数値の違い】
http://php-fan.org/point_calculation.html

投稿2017/02/08 17:04

kei344

総合スコア69366

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirororo

2017/02/08 17:18 編集

小数点を計算する際に、誤差が生じるのですね。大変勉強になります。 サイトを拝見させて頂きます。
hirororo

2017/02/08 17:53

おかげさまで無事、小数点の誤差なく正しく計算出来ました。 いつも的確なアドバイスありがとうございます!
guest

0

$aと$dはどこから来たのか。


質問文のコードが追記されたのでこちらも追記

$twrをechoすれば答えがでると思われます。
1.0033361111111
1.0066777777778
~省略~
1.3572634491172
という具合になりましたよ。

投稿2017/02/08 16:33

編集2017/02/08 16:44
tonarino210

総合スコア228

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirororo

2017/02/08 16:42

おっしゃる通りです。 $aと$dに数値を追加致しました。 $aと$dは本来、POSTで数値を受け取る形を取っておりますが分かりやすいように数値を代入致しました。
tonarino210

2017/02/08 16:47

「$aと$dは本来、POSTにより数値の状態で受け取る」というコメントか情報を書いた方が良いかと。そうなると$twrもどこかで出力されているのですかな?
hirororo

2017/02/08 17:04 編集

早速のお返事、ありがとうございます。 最後の1.3572634491172ですが、 $bに1を代入すると、1.361111111111111と算出されます。 1.361111111111111が正しい答えだと思うのですが、$bに0.01を代入した場合と答えが一致しないので、while文に問題があるのでしょうか?
hirororo

2017/02/08 16:55

アドバイスありがとうございます! 「$aと$dは本来、POSTにより数値の状態で受け取る」 こちら追記させて頂きます。 $twrも最後に出力しますので、追記させて頂きます。
tonarino210

2017/02/08 17:13

なるほど、$b=1だと最終的に $twr=1.3611・・と$b=1.01 になるが、 $b=0.01スタートだと最終的に $twr=1.357・・・と$b=1となる現象ですね。これは小数演算の際に出る誤差が原因で、0.01スタートの方では 0.99の次が1ではなく1.0000000007(くらいだったか)になるためです。  (誤差は処理するコンピュータで様々です。
tonarino210

2017/02/08 17:15

kei344さんのが詳しいのでそちらを参考に。
hirororo

2017/02/08 18:28 編集

そうだったのですね。 そのような誤差があるとは夢にも思いませんでした。プロの方はさすがです。 ありがとうございます!とても勉強になります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問