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

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

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

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

989閲覧

IEEE754 浮動小数点数算術標準の計算ズレに関して

tesopgmh

総合スコア146

PHP

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

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2018/08/23 08:50

編集2018/08/23 08:52

15年間WEB業界にいて恥ずかしながら本日初めて
JavaScriptは小数点の計算が出来ないことを知りました


3万円+消費税(8%)を求めたい
というよくありそうな極々簡単な計算式

alert(30000*1.08);

計算結果は当然32,400円

しかし

JavaScriptの出す結果は「32400.000000000004」
イメージ説明

これはJavaScriptは
IEEE754 浮動小数点数算術標準に準拠しているためのバグ仕様ということが分かりました

そして、ここからが質問なのですが
JavaScriptだけではなくPHPもIEEE754に準拠しているとのことなのですが

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(5.3.3)にて同じ計算をしたところ

echo 30000 * 1.08;

結果は「32400」という正常(一般的な電卓と同じ結果というほうが正確?)な値になるようでした

このPHPとJavaScriptの差はなにによるものなのでしょうか?
IEEE754に準拠は曖昧なものなのでしょうか

お忙しい中恐縮ですが分かる方お教えくださいませ

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

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

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

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

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

guest

回答2

0

ベストアンサー

PHP(5.3.3)にて同じ計算をしたところ結果は「32400」という正常(一般的な電卓と同じ結果というほうが正確?)な値になるようでした

それは見た目だけです。現に、var_dump(30000 * 1.08 === 32400.0);とすれば表示されるのはbool(FALSE)です(3v4l)。

投稿2018/08/23 08:58

maisumakun

総合スコア145121

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

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

tesopgmh

2018/08/23 09:04

ほんとですね、 echo ceil(30000 * 1.08); やってみたら、PHPでも32401という意図しない値になりました https://3v4l.org/AuGNm 丸めて表示していただけだったんですね、勉強になりました
tesopgmh

2018/08/24 07:18

整数に直してから累乗すれば正確な値が出るようなので 各言語の内部でそのような動きにしておいてくれればよいのにと思ったんですが パフォーマンスの問題とかなんですかね
maisumakun

2018/08/24 07:21

そうですね、正確性が必要なら何かしらのライブラリを使ってください、という話です。 0.1すら正確な値を表現できないIEEE 754の2進モードに求めるものでないのは間違いありません。
guest

0

電卓で算出される結果、というのはあくまで、10進の計算で得られる結果です
浮動小数点での計算で得られる結果は2進数の計算で得られる結果です

浮動小数点での計算ずれ、ではなく、あくまで、その結果を10進換算したときに生じる結果ずれです
それをきちんと認識しないとまずいですぜ。

投稿2018/08/23 13:31

y_waiwai

総合スコア87719

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

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

tesopgmh

2018/08/24 07:14

それはgoogleで調べたので知っていますぜ ありがとうございます
y_waiwai

2018/08/24 07:47

それを知ってるなら、小数点の計算ができない、という認識にはならないと思いますが。
tesopgmh

2018/08/24 08:18

質問文をよく読んでください。質問をしているのは小数点がなぜズレるのかではなく、同一の仕様のはずのPHPではなぜズレないのかです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問