doubleをintにキャスト – プログラミング – Home

通知
すべてクリア

[解決済] doubleをintにキャスト


NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

double d = 100;
int i = (int)d;

double d = _tcstod(_T(100), NULL);
int i = (int)d;

極端な例ですが、上記の場合、
iが想定している値にならないケースが発生することはあるのでしょうか?
XP上のVisual C++ 2008では、どちらもiの値は100になるのですが、
これ以外の値でも必ず同じ値になるのかはわかりませんし、
100のケースでも言語的にはどうなのかなと疑問に思っています。

このようなケースでも、四捨五入の処理を入れておくべきものなのでしょうか?


引用未解決
トピックタグ
仲澤@失業者
(@uncle_kei)
Prominent Member
結合: 5年前
投稿: 828
 

>このようなケースでも、四捨五入の処理を入れておくべきものなのでしょうか?

double d = _tcstod(_T(100), NULL);
int i = (int)d;// これは「九捨零入」なので、

「何捨何入」にするかはその目的によります。
「四捨五入」にしたかったらすればよろしいのではないでしょうか。


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

何が訊きたいのか微妙にはっきりしないけど
・ double の内部表現 100.0 は正確に int の 100 に変換できる
・文字列 100 が正確に double の内部表現 100.0 になるかは定かでない
 (変換手段の実装次第:通常は「なる」としても問題ないと思われる)

任意の double 整数が int に変換可能か、といわれればそれは当然無理。
double d=2147483648.0;
int i=(int)d;
は当然ながら符号付き32bit数値に入りきらないので期待通りの値にならない。

Windows というか Intel/AMD CPU の浮動小数点数は IEEE574/IEC559 表記を採用
しているので、例えばこの辺のページを参照。
http://ja.wikipedia.org/wiki/%E6%B5%AE%E5%8B%95%E5%B0%8F%E6%95%B0%E7%82%B9%E6%
95%B0

四捨五入が必要か?は要件次第。
(四捨五入でよいか、銀行丸めでなければならないか、も要件次第)


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

> ・文字列 100 が正確に double の内部表現 100.0 になるかは定かでない
>  (変換手段の実装次第:通常は「なる」としても問題ないと思われる)

これはつまり、100が_tcstod()で99.999...になり、
それをintにキャストしたときに99になってしまっても
仕様的には文句は言えないということですね。

実は、内部で文字列に_tcstod()を使ってdouble値として返すコントロールがあり、
それを整数しか扱わないデータ用にもそのまま使いたいなと思っていて、
返ってくる値は整数文字列をdoubleにしただけのもののはずなので、
戻り値を無条件にintにキャストしてもよいのかなと疑問に感じていました。

99になってしまわないようにするだけなので、
本来は四捨五入である必要も無いのですが、
99.999...と返ってきてしまったものを100として解釈するためには、
どのようなキャストをするべきなのでしょうか?(DBL_EPSILONを使う?)


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

およそ世の中にあるありとあらゆる C/C++ 処理系すべての strtod 変換関数で
100 -> 100.0 という変換がなされるとは限らないか、という設問と

Visual C++ 2008 の strtod/wcstod で _T(100) が 99.999 になりうるか、
という設問では、内容が異なりすぎる。

後者であれば strtod の実装を検証してみればよいだけの話。
とりあえずウチの VS2005 の crt/src/strtod.c を見てみた。
実変換を行っている部分はアセンブラの _fltin2 でソースが無いっぽいっす。

ただ、ごくごく簡単にそういう変換関数の実装を想像するに
・変換結果が int の範囲に収まる
・変換前の文字列表記には小数点文字 . や指数文字 E が含まれない
のであれば、変換演算として実行される式は単純に
(直前までの桁)*10 + 注目中の桁
であって、この式中に現れるすべての値が exact である以上は精度落ちは無い、
つまり必ず 100.0 になり、絶対に 99.999 になるわけがない、
と思われるのだがどうだろうか。
# 責任持つ気まったく無し。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

tetrapodさんが書かれているように

いかなる場合でもと言う話とVS2005ではと言う話では
考えるべき内容が異なりますよね。

現在の開発環境の範囲で保証したいのであれば、
その中で保証できるかを確認すれば良いのではと思います。
未来永劫保証しろと言うのは多分無理なので。

で、100がうまくいけはそれで良いの?
と言う話もあります。
2進数表現で実数を表現する限界がある以上は
うまく行かない数値もありますからその場合も含めて
と言う話ならそれなりに対策が必要になるかもしれません。
それこそ「何捨何入」にするかは目的次第と言う話なので
その判断はシステムの使用が理解できている人の仕事に
なると思います。


返信引用
PATIO
(@patio)
Famed Member
結合: 3年前
投稿: 2660
 

あう。

誤字が。

「システムの使用が」ではなくて「システムの仕様が」ですね。


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

若干補足させてもらうと

double 「数値D」 = _tcstod(「数値文字列」, NULL);

のとき、「数値D」には、「数値文字列」のあらわす、純粋に数学的数値が
入らない場合があります。

まぁ、それとは関係なく、そもそもint値が取得したいのならば
ユーザーが誤り無くint値を入力できるインターフェースを
使用すべきだと考えますが、どうでしょう。


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

若干補足させてもらうと

double 「数値D」 = _tcstod(「数値文字列」, NULL);

のとき、「数値D」には、「数値文字列」のあらわす、純粋に数学的数値が
入らない場合があります。

まぁ、それとは関係なく、そもそもlong値が取得したいのならば
ユーザーが誤り無くlong値を入力できるインターフェースを
使用すべきだと考えます。


返信引用
かも
 かも
(@かも)
ゲスト
結合: 14年前
投稿: 2
 

double を int にキャストする時点で危険が伴うと思います。
必要に応じた処理を書くほうがよいかもしれません。


返信引用
NOR
 NOR
(@NOR)
ゲスト
結合: 23年前
投稿: 128
Topic starter  

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

おとなしく、値をintで返すメンバ関数をコントロールに追加し、
「整数を扱うモードのときは、こっちの関数で値を取得すること」
という仕様にしておきます。


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

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