四捨五入の方法

[戻る]
こうちゃ 2003/02/03(月) 17:21:19
float型、double型の値を任意の小数点以下を四捨五入にする関数、または方法をご存知の方が
いましたら教えていただけませんでしょうか。MSDNで調べてはいるのですが分かりません。
環境はWin2000、VC++6.0です。

επιστημη 2003/02/03(月) 17:40:38
floor, ceil をMSDNから探しましょう。

wood 2003/02/03(月) 17:42:10
必要とする精度にもよるのですが
一度文字列変換してから行う方法でやったことあるよ
+とかーの判断も必要でしたし、少数以下第何位までの精度がほしいかにもよるし

関数だけで何とかしようとしても思ったとおりの結果
にならないみたいですよ

四捨五入専用関数はないとおもいますけど?

επιστημη 2003/02/03(月) 17:43:21
...ごめん、マチガイというか、補足。

0.5を加えてからfloorを呼び出せばよさげです。

四捨五入の結果をintで欲しいなら:
double x = ...;
int n = (int)(x + 0.5);

アイススケーター 2003/02/03(月) 18:05:17
「任意の小数点以下を四捨五入」というのがネックと思います。

小数点以下の四捨五入ならばεπιστημηの方法でよいと思いますが、
  0.004→0.00
  0.005→0.01
のような場合は、一度100を掛けてから四捨五入した後に、100で割るでどうでしょう

επιστημη 2003/02/03(月) 18:06:56
あ...フォローありがとうございます。

八郎 2003/02/03(月) 18:24:58
四捨五入した結果をfloat型、double型に戻すと、期待した値にならない場合もあるかも
(^^)

PAI 2003/02/03(月) 19:01:49
手元にこんなのがありました。むかーし作った奴です。


double Pai::Round( double value, int figure )
{
    bool isNagative = ( value < 0 );
    if( isNagative ) value = -value;

    double rate = pow( 10, figure );
    int tmp =  int(value * rate + 0.5);
    value = tmp/rate;

    if( isNagative ) value = -value;
    
    return value;
}

こうちゃ 2003/02/03(月) 20:01:07
[[解決]]
みなさんありがとうございました。
私も0.5をプラスしていろいろして試みましたがPAIさんのが分かりやすく使いたいと思いま
す。
結構安易に考えていたのですが、意外と四捨五入は難しいものですね。
勉強になりました。

PAI 2003/02/03(月) 20:48:29
うお、Nagativeってなんじゃ?

・・・恥ずかし。

EIJI 2003/02/04(火) 11:50:50
解決しちゃったぽいですが・・

doubleで計算してintにキャストし、あとで割る方法を使うと
数値によってはintにキャストした時点で誤差が出てしまい
正しい結果が得られないことがあります。

試しに Round(1.005,2) (3桁目で四捨五入)をしてみると
結果が 1.01にならず 1.0 になります。
floor使ってもたぶん同じ結果だったような。

PAI 2003/02/04(火) 12:14:24
なるほど、奥が深いですね。
100.5+0.50 は 101 に100の方向から十分近い、101より小さい数になってしまうわけですね。

・・・0.501足すとか・・・だめですかね。

やっぱり一旦文字列に換えて、とかやる必要があるんでしょうか。

EIJI 2003/02/04(火) 12:33:39
浮動小数点数を使う限りこの問題は避けられないと思います。
2進化10進数(BCD)ライブラリを使うとよいそうですが、
私自身は使ったことないです(^^;

こうちゃ 2003/02/04(火) 15:30:53
解決したつもりでいましたが、甘かったようです。。。
確かに期待通りの値が出ませんでした。(ガッカリ・・・)
一旦文字列にして地道に四捨五入をしないと駄目なのですかね?
本当に安易に考えていました。

επιστημη 2003/02/04(火) 15:46:19
もともと'おおよその値'を求めるのが目的の四捨五入に
それほどの精度を必要とするのですか?

NEG(ねぐ) [E-Mail] [HomePage] 2003/02/04(火) 21:38:09
 ceilで問題ないと思うけど、、、

    double dou=1.005;
    TRACE("Round=%lf\n",ceil((dou+.005)/.01)*.01);

http://www24.cds.ne.jp/~neg/pro/piyo1/cetc/dou.html

NEG(ねぐ) [E-Mail] [HomePage] 2003/02/04(火) 22:07:12
 ちょっと違った。
 Roundで補正して、floorで不要桁をカットします。
<負の値の時は少し考えないといけない。

#define Round(n,r) (n>0?ceil(n/r)*r:floor(n/r)*r)
    double dou=1.005;//4;//
    TRACE("Round=%lf\n",floor((Round(dou,.001)+.005)/.01)*.01);

EIJI 2003/02/05(水) 11:18:46
dou を変えると誤差が出ちゃいます。
1.025とか。

NEG(ねぐ) [E-Mail] [HomePage] 2003/02/05(水) 11:37:01
 補正位置が悪いようだ。
 こうかな???
    TRACE("Round=%lf\n",floor((Round((dou+.005),.001))/.01)*.01);

wood 2003/02/05(水) 12:41:40
こうちゃ さん まだ話が続くなら 管理人さんに「済」マークはずしてもらってください
話が終わっているなら良いのですけど


>一旦文字列にして四捨五入
「MSは切り上げ・切り捨て・四捨五入についてはIEEEの規格に則って作っています」
昔MSから、こんな回答をもらったことがありましたね
関数だけで解決しようにも解決つきませんでしたから

この方法のソース昨日見つけました、
但し VC++1.0でC覚えたての頃のもの、なのでかなり汚いですけど
いりますか?

工業系のCOBOLシステムをC言語にコンバートしてPCで動作できる
用にしたときのものです

少数以下の精度は10桁くらいは大丈夫なはずです
サイン+整数+少数 全体で18桁くらいに制限していたはずですけど
(多少のバグあるかも?)

ほしいなら載せますけど、載せられるのは早朝か深夜になります
(会社には持込していないので)

>「済」マークはずし
がこのスレッドの条件になりますけど
どこで話が終わってるか、わからないので

古いスレッドには追加発言できません。