double型について – プログラミング – Home

通知
すべてクリア

[解決済] double型について


めあ
 めあ
(@めあ)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

環境:VS2008、MFC

double型で宣言した数値に「4.2」などの数字を入れ、
ブレークを張って中を見てみると「4.199999.....」となってしまいます

そのため、#define 4.2 と定義したものと整合性がとれません

きちんと「4.2」が入るにはどうすれば良いのでしょうか?


引用未解決
トピックタグ
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 15年前
投稿: 64
 

「整合性がとれない」とはいかなる意味ですか?
double,floatには誤差がつきものです。
有限の桁数ではどんなにがんばっても1/3を正確には現わせないのと同じこと。
# なので == で等値判定をしてはなりません。


返信引用
めあ
 めあ
(@めあ)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

== で等値判定が出来ないという意味でした。
== はいけないのですね

一度、#defineの値をdouble型に入れてから==で判定するなどしないといけないのでしょ
うか?
何かスマートな判定方法はないのでしょうか?


返信引用
επιστημη
 επιστημη
(@επιστημη)
ゲスト
結合: 15年前
投稿: 64
 

> 一度、#defineの値をdouble型に入れてから==で判定するなどしないといけないのでし
ょうか?

いやだから == 使っちゃダメだってば。


返信引用
めあ
 めあ
(@めあ)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

数値にも、strcmpのようなAPIがあるのでしょうか?
探し方が悪いのか、検索で見つかりませんでした

もしくは、小数点を含む数値の比較ってMFCではできないのでしょうか?


返信引用
しま
 しま
(@しま)
ゲスト
結合: 18年前
投稿: 123
 

επιστημηさんが書いてらっしゃいますが
普通の計算機での実数の扱いは浮動小数点数という
固定長(つまり有限の桁数)の表現方式で取り扱います。
その上、2進数(10進ではない)なので10進で
有限の桁数で表現できるものでも二進では極僅かに誤差が
出てしまうことがありますし、有限の桁数では表現できない
こともあります。

#define 4.2 とソース上に書いてあるからといっても
コンパイルした時に十進で 4.2 が、2進数での浮動小数点数
がたまたま誤差を含まないとしても、比較相手がぴったり
4.2 という保証がどこかにありますか?
比較相手が例えば 4.2000013 という場合単純に等号で比較しても
不一致と判定してしまいす。誤差の範囲に収まっていれば
等しいと判定するのが浮動小数点数の場合通常なのです。


返信引用
壱
 壱
(@壱)
ゲスト
結合: 14年前
投稿: 9
 

単純に考えるのであれば、範囲で比較するしかないのではないでしょうか。

#include <iostream>
#include <float.h>

if ( (srcValue - DBL_EPSILON) < destValue &&
destValue < (srcValue + DBL_EPSILON ) )
{
std::cout << OK << endl;
}


返信引用
みい
 みい
(@みい)
ゲスト
結合: 22年前
投稿: 65
 

私の場合は判定が必要なデータは整数化しています
(値を計算する場合は、計算途中はdoubleで行い
最終結果を整数化)。

有効桁数分を10のN乗をかける

0.1の桁を四捨五入

整数型でキャスト

※とうぜん比較値も整数化しています。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

静観してましたが、やや気になるので発言します。一般に
#define AAA 4.2
void Foo()
{
double bbb = ( double)4.2;
if( bbb == AAA){
// 一致した(必ず一致します)。
}
}
は、「完全に正しい」コードで、「一致した」に必ず入ります。
当然ですが、エラーも警告もでません。
これは、比較演算子==が実行されるとき、AAAを自動的にdouble値に
変換するからです。
これを踏まえた上で、めあさんが、どのようなコードで「一致しない」
状況になっているのかを、再度確認してみたいのですが、いかがでしょう。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

私も仲澤さんに賛成です。
以下のコードを実行すると

double d0 = 1.0 / 3.0;
double d1 = 1.0 / 3.0;
double d2 = 1.0 / 3;
double d3 = 10.0 / 3.0 / 10.0;

TRACE(d0 %s d1\n, (d0 == d1) ? == : !=);
TRACE(d0 %s d2\n, (d0 == d2) ? == : !=);
TRACE(d0 %s d3\n, (d0 == d3) ? == : !=);

結果はこうです。
d0 == d1
d0 == d2
d0 != d3

結果として同じ値が期待される演算ではなく、
全く同じ演算を行えば全く同じ結果が得られるのは
当然といえましょう。


返信引用
bun
 bun
(@bun)
ゲスト
結合: 24年前
投稿: 761
 

要するにめあさんに聞きたいのは、
・結果として同じ値が期待される演算結果の比較なのか?
・全く同じ演算結果の比較なのか?
どちらなの?ということです。

前者なら他の人のおっしゃる通りですし、
後者なら一致してしかるべきですので、何か別の問題が
あるはずです。


返信引用
ITO
 ITO
(@ITO)
ゲスト
結合: 22年前
投稿: 1235
 

>もしくは、小数点を含む数値の比較ってMFCではできないのでしょうか?
strcmpのような関数はないです。

マイクロソフトがすすめる方法は、
 みいさんの
   2011/11/28(月) 09:49:36
 の方法です。
僕も、どうしても比較なければいけない場合は、同じ方法を使います。

もし、ある程度許されるのであれば、範囲で判定します。


返信引用
めあ
 めあ
(@めあ)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

みなさんご回答ありがとうございます

仲澤さんやbunさんがおっしゃるとおり、
== で「一致した」ということになっていました。
値を中を見て、不動小数点が入っているので
一致しないものと勘違いしておりました。すみません。

ちなみに、自分がやろうとしていた事は、
・アプリからバージョンを取得
・バージョンがX.XX以下なら除外

というものを想定していました
なので、正確には==ではなく<=ですね

しかし、浮動小数点が絡む計算については勉強になりました
今後、使う事があれば参考にさせてもらいます。ありがとうございました。


返信引用
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

ですか。とりあえずはうまく動くのかもしれませんが、
本来「バージョン番号」と「浮動少数(又は実数)」とは関係の無い「型」です。
「バージョン番号」型の「<=」演算をdouble型の「<=」演算で代用するのは
間違いであると言わざるをえません(vv;)。

(将来想定される問題)
バージョンが MM.ss.bb 形式に変更になった( ver 4.1.1 等)。
数値の後ろにアルファベットが入ることになった( ver 4.1b 等)
・・・とか。


返信引用
めあ
 めあ
(@めあ)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

あ、なるほど

無理にdouble型に直さないまでも、「.」で区切って
個々の数字として判定すれば良かったのですね
思いつきませんでした。

Ver4.1.1等のバージョンも存在するかもしれないとのことなので、
この方式でやってみようと思います。ありがとうございます。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました