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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

7624閲覧

floor,ceil関数と整数の等価比較について

Eki

総合スコア429

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

3グッド

1クリップ

投稿2017/07/01 15:02

よくdouble同士の==による比較は危険だと言われます。実際,二進数で表せないような小数はどうしても切り捨てによる誤差が生まれる,ということは分かります。

そこに小数を(double型の)整数で返すようなfloorceilといった関数があります。整数はdouble型で確かにきっかり表せると思いますが,僅かにゴミの残ったほとんど整数,のような値が返ることはないのでしょうか。そうだとすると,このような関数が返すような整数値は==で比較してもよいのでしょうか。(ただし,関数に渡す値にINFやNaNや非正規化数などの変な入力はないとします。)

一応,例えば次のようなプログラムを書いてみて,自分の環境ではこれが1を表示したはしたのですが

cpp

1double x = floor(2.1); 2std::cout << (x == 2.) << std::endl;

自分の環境では次のプログラムも同様に1を表示するので,誤差が現れていないだけなのか,存在しないのか,2.1という数字が都合良かっただけなのか,自分には分かりません・・・。

cpp

1double x = 0.5; 2double y = 0; 3for (int i = 0; i < 5; i++) { 4 y += 0.1; 5} 6std::cout << (x == y) << std::endl;

お力をお貸しください。

環境

sh

1$ clang++ --version 2clang version 4.0.0 (tags/RELEASE_400/final) 3Target: x86_64-unknown-linux-gnu 4Thread model: posix 5InstalledDir: /usr/bin
faithandbrave, LouiS0616, yohhoy👍を押しています

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

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

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

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

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

guest

回答3

0

ベストアンサー

こんにちは。

例えば、floor関数で想定外の切り捨てが発生しないのであれば、切り捨て後の比較で問題はでません。

しかし、切り捨てはなかなか怖くて、0.9999999999999999999999は0になります。
実は誤差のない計算であれば1.0になるような場合でもです。

切り捨て時、切り上げ時にこのようなケースがあっても問題にならないケースであれば大丈夫な筈です。

投稿2017/07/01 15:45

Chironian

総合スコア23272

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

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

Eki

2017/07/01 15:55

回答ありがとうございます。 確かに落とし穴になりそうですね。 ただ,この場合でも切り捨て後の整数は厳密に0と一致するということですね。 少しだけ反れますが,一般に2進小数で表せるような数だけを経由した四則演算の結果(で非正規化数とか変な数にもならない場合)は誤差が入りようがないと思うのですが,厳密に==で比較できますか。
Chironian

2017/07/01 16:30

(10進数から内部表現への変換と==も含む)全ての計算過程で丸めも桁落ちも発生しなかったら==で厳密に比較できると思います。
Eki

2017/07/06 13:51

ありがとうございます,納得しました。
guest

0

C99およびC11の規格において、floor()ceil()は整数値が返ると規定されているので、問題ありません。(NaNとINFを除く)

7.12.9.1 The ceil functions
The ceil functions compute the smallest integer value not less than x.

7.12.9.2 The floor functions
The floor functions compute the largest integer value not greater than x.

投稿2017/07/03 05:26

faithandbrave

総合スコア132

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

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

Eki

2017/07/06 13:50

回答ありがとうございます。遅くなり申し訳ありません。 なるほど,ありがとうございます。規格はやはり安心感が違いますね。
guest

0

通常は浮動小数点の表現は仮数部と指数部から成ります。 このとき指数部が 0 であれば実質的に整数であり、誤差のない比較が可能です。

投稿2017/07/01 15:31

SaitoAtsushi

総合スコア5444

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

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

KSwordOfHaste

2017/07/01 15:38

「仮数部の小数点以下の桁が0」というべきではないでしょうか?
Eki

2017/07/01 15:47

回答ありがとうございます。浮動小数点数で指数部が0になるとき,つまり普通に整数を代入するようなときは,誤差のない比較ができるということですね。 floor関数やceil関数がどのように実装されているかを私は知らないのですが,もし何らかの計算で求めているとしても,その計算の過程で微妙なゴミが残るようなことはない,ということでよいのでしょうか。
yumetodo

2017/07/02 11:06

ただし規格上の保証はないはず(IEEE754ではない環境ふくめ大丈夫だと思いますが)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問