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

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

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

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Q&A

解決済

3回答

2799閲覧

CString型の文字列からdouble型への変換で誤差を発生させない方法について

AkatsukiMizuki

総合スコア1

CSV

CSV(Comma-Separated Values)はコンマで区切られた明白なテキスト値のリストです。もしくは、そのフォーマットでひとつ以上のリストを含むファイルを指します。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

0グッド

0クリップ

投稿2020/05/25 08:52

編集2020/05/26 04:44

前提・実現したいこと

Windows10+Visual C++ 2017の環境にて
CSVファイルから取得した数値データを処理するプログラムを作成しています。

CSVからの文字列取得にはCStdioFileのResdStringを使用してCString型の変数に格納しています。
CSVには下記のように小数点以下8桁の数値が入力されています。(負の数有り)

 "0.10000000", ”-0.30000000”, "-0.59564810"・・・

発生している問題

ここで下記のようにwcstodを使用して文字列からdouble型の変数に変換して代入したところ誤差が発生しました。

CString strMoji; double dSuuchi; dSuuchi = wcstod( strMoji, NULL);

結果、strMoji = -0.30000000がdSuuchi = -0.29999999999999999になってしまいました。
誤差の出ないように型変換するにはどのような方法がありますでしょうか。

追記

この後の処理でdSuuchiを計算式にて再計算した値を再びCSVに書き込む処理となっています。
変換された時点のdSuuchiの値をデバッガで確認した結果上記となっています。

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

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

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

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

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

maisumakun

2020/05/25 09:02

本当に10倍の値になってしまったのですか?
ikadzuchi

2020/05/26 01:12

結果はどのように確かめていますか?
AkatsukiMizuki

2020/05/26 04:45

追記の通り、変換されたdSuuchiの値をデバッガにて参照しています。
guest

回答3

0

ベストアンサー

桁数が変わっていますね。
(最初に質問に書かれていた桁数の)-0.29999999は-0.30000000と異なりますが、
-0.29999999999999999と-0.30000000は(doubleとしては)同一の値です。
同一なので、そのdouble値を表示した時に-0.29999999999999999と-0.3のどちらで表示されるかは環境に依存します。
気の利いた環境ならデフォルトで-0.29999999999999999ではなく-0.3と表示してくれることもあるでしょう。
小数点以下8桁しか無いと分かっているなら四捨五入すれば明示的に-0.30000000と表示させることができます。

参考: 浮動小数点数の10進指数表示のアルゴリズム

投稿2020/05/26 05:18

ikadzuchi

総合スコア3047

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

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

0

問題は、double型への代入ではなく、あとの処理の方ではないかと思います。

doubleは2進法で値を保持するので、「10進8桁で丸める」という前提であれば正しく表示できる値は保持できますが、その厳密な値は異なってきます。演算の結果、その差が10進8桁で見える範囲内に影響してくる、ということも考えられます。

投稿2020/05/26 01:20

maisumakun

総合スコア146018

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

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

maisumakun

2020/05/26 04:46

> 変換された時点のdSuuchiの値をデバッガで確認した結果上記となっています。 8桁で四捨五入すれば正しい値になるかと思います。
guest

0

誤差の出ないように型変換するにはどのような方法がありますでしょうか。

不可能です
double型というのは、2進数で小数点以下も含め表現する実数型です
あなたが使っている10進数に(から)変換するときに、近似値となってしまいます。
#10進数の0.1はdoubleでは表現できません

これはどうしようもないので、どうしてもその誤差なるものを避ける必要があるなら、10進演算用のクラスを作るか探してくるかしましょう

投稿2020/05/25 10:30

y_waiwai

総合スコア88042

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

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

AkatsukiMizuki

2020/05/25 11:20

ご説明ありがとうございます。 やはり近似値となるのは避けられないんですね。 自作クラス作成に挑戦してみます。
ikadzuchi

2020/05/26 01:10

いいえ。doubleの精度は10進15桁ほどありますので0.30000000は正確に復元できてしかるべきです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問