- PR -

四捨五入

投稿者投稿内容
Jitta
ぬし
会議室デビュー日: 2002/07/05
投稿数: 6267
お住まい・勤務地: 兵庫県・海手
投稿日時: 2003-07-29 09:07
引用:

meiさんの書き込み (2003-07-28 21:09) より:

多分、偶数丸め。


ISO 31-0です。
http://www.dataaction.co.jp/bunsyo-j.htm
xkimura
会議室デビュー日: 2002/12/18
投稿数: 11
お住まい・勤務地: 新潟県
投稿日時: 2003-07-29 11:11
私は次のような関数を作成して四捨五入しています。参考までに...


引数"Figure"に-5をセットすると1万の位で四捨五入します。
--------------------------------------------------------------------------
Public Function Round(ByVal value As Double , Optional ByVal Figure As Integer = 0) As Double
Dim dblData1 As Double = 0
Dim dblData2 As Double = 0
Dim dblRound As Double = 0

dblData1 = value * (10 ^ Figure)
dblData2 = dblData1 + System.Math.Sign(value) * 0.5 '四捨五入

'参考までに切り上げ、切り捨ての計算です。
'dblData2 = dblData1 + System.Math.Sign(value) * 0.9 '切り上げ
'dblData2 = dblData1 '切り捨て

dblRound = Fix(dblData2) / (10 ^ Figure)
Return dblRound
End Function
--------------------------------------------------------------------------


[ メッセージ編集済み 編集者: xkimura 編集日時 2003-07-29 11:12 ]
yamasa
ベテラン
会議室デビュー日: 2003/02/15
投稿数: 80
投稿日時: 2003-07-29 13:57
引用:

ななさんの書き込み (2003-07-29 08:28) より:
> 計算に浮動小数点を使用していた場合、丸め誤差により
> 正しくない値になってしまうことがあります。

float型を使用しているのが問題だと思いますが。
float -> double にした場合、ビット0でAppendされる。)

わたしの場合、浮動小数点型をdoubleに統一することで回避しています。


いいえ、doubleにしても誤差が小さくなるだけで、
本質的には何も解決されていません。
コード:
using System;
class Sample2 {
  static long MyRound(long value) {
    return (long)(value / 100000.0 + 0.5) * 100000;
  }
  static void Main(string[] args){
    Console.WriteLine(MyRound( 9000000000049999));
    Console.WriteLine(MyRound(10000000000049999));

    // おまけ: 0.1を55回加算してからRound()
    double value = 0.0;
    for (int i = 0; i < 55; i++) {
      value += 0.1;
    }
    Console.WriteLine(value);
    Console.WriteLine(Math.Round(value));

    // 5.5を直接Round()
    Console.WriteLine(Math.Round(5.5));
  }
}
--実行結果--
9000000000000000
10000000000100000
5.5
5
6
------------


浮動小数点には誤差があって当然だということを
常に認識しておくべきです。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2003-07-29 14:22
引用:

いいえ、doubleにしても誤差が小さくなるだけで、
本質的には何も解決されていません。


や、longにしたらそりゃそうですが、ここで書かれてたのはintの時の話では?
# 深く考えてないので浮動少数に関する他の問題もあるかもしれませんが。

例が単に精度(有効桁数)オーバーのもののような気がしますが、ちょっとここでは話が違うような気がします。
引用:

浮動小数点には誤差があって当然だということを
常に認識しておくべきです。


あ、もちろん、この話には異存はありません。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2003-07-29 14:29
引用:

例が単に精度(有効桁数)オーバーのもののような気がしますが、ちょっとここでは話が違うような気がします。


あ、整数のままやるやり方はどうだとか、浮動少数を使うべきだとか、そういう意図で書いたのではありませんので。
単に、ここで前の誤差の例をあげるのは、ちょっと話が違ってしまいそうと思っただけです。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2003-07-29 14:50
unibon です。こんにちわ。

#私は .NET は知らないのですが、
#以下、昔の VB/VBScript と同じだろうという前提で書きます。

引用:

yamasaさんの書き込み (2003-07-29 13:57) より:
static long MyRound(long value) {
return (long)(value / 100000.0 + 0.5) * 100000;
}



long のキャストは、切捨てではなく、四捨五入に似た丸めかもしれません
(これはちょっと自信がありません。でも VB/VBScript の CLng はそうでした)。

引用:

yamasaさんの書き込み (2003-07-29 13:57) より:

Console.WriteLine(MyRound( 9000000000049999));
Console.WriteLine(MyRound(10000000000049999));

// おまけ: 0.1を55回加算してからRound()
double value = 0.0;
for (int i = 0; i < 55; i++) {
value += 0.1;
}
Console.WriteLine(value);
Console.WriteLine(Math.Round(value));

// 5.5を直接Round()
Console.WriteLine(Math.Round(5.5));

--実行結果--
9000000000000000
10000000000100000
5.5
5
6
------------


0.1を55回加算すると、Console.WriteLine の出力は 5.5 に見えますが、
実際には 5.5 より小さい値(5.499999...)になっているのでしょう。
すなわち、Console.WriteLine が過度に丸めています。
したがって、この段階ですでに変数の値が誤差を持っていることになります。

#以下、あとで追加。
Console.WriteLine が丸めているわけではなく、
数値を文字列に変換するモジュールが丸めています。

[ メッセージ編集済み 編集者: unibon 編集日時 2003-07-29 14:52 ]
yamasa
ベテラン
会議室デビュー日: 2003/02/15
投稿数: 80
投稿日時: 2003-07-29 15:17
引用:

なちゃさんの書き込み (2003-07-29 14:22) より:
や、longにしたらそりゃそうですが、ここで書かれてたのはintの時の話では?


まあ確かにそうなんですが、ここでの私の発言は、
ななさんの
> わたしの場合、浮動小数点型をdoubleに統一することで回避しています。
という発言が「全てdoubleを使っていれば浮動小数点の誤差も気にしなくてよい」という
誤解を招きかねないと思ってのものです。

# 金利の計算に浮動小数点型を使われて、ただでさえ少ない利息が
# さらに減らされでもしたら目も当てられませんからね。
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2003-07-29 15:31
引用:

> わたしの場合、浮動小数点型をdoubleに統一することで回避しています。
という発言が「全てdoubleを使っていれば浮動小数点の誤差も気にしなくてよい」という
誤解を招きかねないと思ってのものです。


あ、意図はよく分かりました。
もちろん、浮動小数点の問題は軽視してよいものではないです。
# この辺は意外に(どころか全く)知らない人も結構いてびっくりしたりしますね。

ま、私が書いたのはただ「ここの今の例としては」という話ですので。

スキルアップ/キャリアアップ(JOB@IT)