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

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

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

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

Q&A

解決済

3回答

300閲覧

浮動小数点の処理について

u-sukesan

総合スコア159

PHP

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

0グッド

1クリップ

投稿2024/07/24 13:04

実現したいこと

141,750 - 20,817 = 120,933
としたい

前提

PHP7.x
chrome

以下ブラウザ上でフォームから数値を入力しPHPにてMysqlに保存する
という給与計算システムです。

給与 141750円という支給額をフォーム入力し

これに対して所得税やもろも計算をPHPにて計算したのち
控除額の合計が

20817 となった

単純に141750 ー  20817 として支払額を計算する

Mysqlにも支給額141750 と 控除合計20817 として保存されている

発生している問題

減算の結果が120,934円となる

該当のソースコード

PHP

1//支給額 2$bonus[0]="141750"; 3 4//控除計 5$bonus[8]=floor((string)($bonus[1]+$bonus[2]+$bonus[3]+$bonus[7]+$bonus[10]+$bonus[11]+$bonus[12]+$bonus[13])); 6//支払額 7$bonus[9]=$bonus[0]-$bonus[8];

試したこと

浮動小数点というものを知り
下記のように修正
$bonus[9]=floor((string)($bonus[0]-$bonus[8]));

ほとんどはこれで正常に処理されたが、一部の人だけ変わらず1円ずれる

$bonus[8]の中身のそれぞれの計算を膨大になりますので書けないのですが
floor((string)(A-B))

①上記の処理でも解決できない浮動小数点というものが存在するのかどうかを聞きたい
②その厳密な処理に関してはPHPでは限界があるのかを聞きたい

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

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

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

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

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

otn

2024/07/24 14:14 編集

実行可能なコードが掲載されてないので、「書かれてない部分で、どこか間違ってるのでしょう」としか言い様がないです。間違いなく書いているのであれば、6桁7桁程度の整数値の演算で誤差は出ません。 膨大なコードを載せられてもしょうがないので、とりあえず、お書きのコードで言うと7行目のあとに、 var_dump( $bonus[9], $bonus[0], $bonus[8]); を書いて、その出力を「コピペ」しましょう。 $bonus[0] は整数を表す文字列なので、誤差が出るのであれば、$bonus[8] が整数でないと思われます。
u-sukesan

2024/07/25 00:20

ありがとうございます! 全ての数値をdumpしてみたところ おっしゃられる通り$bonus[8] が整数でなくmysql格納時にint型のため小数点以下が繰り上げされて保存されていたことがわかりました。 大変重要なヒントになりました。 ありがとうございます
otn

2024/07/25 10:50 編集

「値を確認する」は、デバッグの第一歩です。 「現状がどうであるか」を確認することなしに、思いつきで試行錯誤しても解決しません。
otn

2024/07/25 10:49

質問とは関係ないですが、 ・データ型全般 ・中でも特に数値型 について復習した方がよいでしょうね。
guest

回答3

0

ベストアンサー

Mysqlにも支給額141750 と 控除合計20817 として保存されている

保存しているMySQLテーブルのカラムがint型であれば丸められます。

具体例を上げますと 20816.5 をinsertすると 20817 と保存されます。
対してPHPでの floorは切り捨てですので、 floor("20816.5") の結果は float(20816) になります。

MySQLのデータ型が正しくない、あるいは計算式の端数処理が正しくない可能性が高そうですので、そのあたりを見直すとよいかと思います。

投稿2024/07/24 15:59

Eggpan

総合スコア3190

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

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

u-sukesan

2024/07/25 00:30

回答ありがとうございます。 いただいたヒントを参考に試したところ問題が解決しました! ベストアンサーに選ばせていただきました。
guest

0

控除額を丸めてから引き算すればいいのではないでしょうか。

投稿2024/07/24 13:20

maisumakun

総合スコア145628

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

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

u-sukesan

2024/07/25 00:31

回答ありがとうございます。 結論、控除額それぞれを四捨五入、切り捨てを行ってから合計した結果、正常に処理されました
guest

0

はっきりとはしていませんが おそらく下記のような丸め誤差の現象だと考えられます。

以下参考サイトから引用

<?php $num = (0.1 + 0.7) * 10; echo floor($num); ?>

7
「(0.1 + 0.7) * 10」をfloorで切り捨てるので、実行結果が「8」になると思ってしまいますが、「7」という結果になります。
引用テキスト
これは丸め誤差によるものです。コンピュータの内部では、数値をすべて2進数で扱いますが、10進数であれば正確な数で表せる数でも、2進数では正確に表せない数があります。
引用テキスト
正確に表せない数はある程度の桁数で値を省略することになり、誤差が生じます。これを丸め誤差といいます。
引用テキスト
サンプルで使用している「0.1」「0.7」は2進数で正確に表せない数の例であり、丸め誤差により$numの値は「7.999999999999…」となってしまい、予想外の結果になってしまいます。

控除額それぞれを四捨五入、切り捨てを行ってから合計したものを支給額から減算したところ結果、正常に処理されました

投稿2024/07/25 00:58

u-sukesan

総合スコア159

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.40%

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

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

質問する

関連した質問