- - PR -
四捨五入
投稿者 | 投稿内容 | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2003-07-29 20:39
ども。raccoonです。
いやぁ,四捨五入ひとつにもいろいろあって,勉強になります。 特にunibonさんが紹介してくれたのがスマートで気に入りました。 そこで, x = 2367896 y = x + (x Mod 10000) z = y - (y Mod 10000) なんてどうでしょう? # 出してから気が付いた。 # これでじゅうぶんでしたね。 x = 2367896 y = x + 5000 z = y - (y Mod 10000) [ メッセージ編集済み 編集者: raccoon 編集日時 2003-07-29 20:48 ] | ||||||||||||||||||||
|
投稿日時: 2003-07-29 21:01
ここでは一万の位で四捨五入する話ですので
raccoon さんの前者の方法はなかなかおもしろいですね(計算としては無駄だけど)。 [ メッセージ編集済み 編集者: IZUMI Yusuke 編集日時 2003-07-29 21:04 ] | ||||||||||||||||||||
|
投稿日時: 2003-07-29 22:19
IZUMI Yusukeさん,コメントありがとうございます。
わたしも我ながらフシギなやり方しちゃったなぁ,と笑ってます。 「modした値をうまく使えないか?」という出発点で考えたことが原因のようです。 最初の考えにつかまって,そこからすぐに抜け出せないとは・・・。たぶん年のせいです。 # 技術者として曲がり角にきたんじゃないのか?大丈夫か?->オレ わたしの後者の方法は,『5を足してから切り捨てる』ということで, このスレの最初のほうにある,Jittaさんやxkimuraさんのやり方と 本質的には似たようなものですね。切り捨ての方法が違いますが。 その意味では,前者の方はたしかに異質で面白いといえますが・・・。 いやぁ,お恥ずかしい。# しかもいつのまにか「常連さん」になってるのに・・・ | ||||||||||||||||||||
|
投稿日時: 2003-07-29 22:34
本題とは離れてしまいますが、誤差を出来るだけ避けるなら、
doubleよりもdecimal型の方が良いですね。 整数部とスケールファクタで成り立っているので、 浮動小数点数のdoubleみたいな誤差は出ないし。 Cとかだと馴染みが無い型なので、ついつい忘れてしまいます(笑)。 | ||||||||||||||||||||
|
投稿日時: 2003-07-29 23:39
まあ、MyRoundの実装に限って言えば、 おっしゃる通り正しい結果が得られますね。 # value / 100000.0 の時点で小数部分に必要な情報は # 0.5 を加えると繰り上がるかどうかだけなので、 # value そのものが浮動小数点型で正確に表現できていれば # 誤差の影響は受けない。 ただし一般論としては、float や double 型で小数を扱う場合に 誤差の影響を注意深く考慮しなければならないことに変わりはありません。
それは確かにそうなんですが、たとえば Int32.MinValue 以上 Int32.MaxValue 以下の 整数を表現するには、int型が一番適していますよね。
数値型の内部表現をdouble型に統一してしまった言語もありますが、 そういうのはC#等の流儀には反しているでしょう。 | ||||||||||||||||||||
|
投稿日時: 2003-07-29 23:49
# 最初、スレッド一覧を見たとき、四捨五入が燃えてるので思わず笑ってしまいました。失敬。
# 大昔のBASICの時はあんまり考えずにやってたような記憶があります。懐かしい。 | ||||||||||||||||||||
|
投稿日時: 2003-07-30 00:04
大昔のBASICには10進浮動小数のものがあったりしたような。 この場合、有効桁数の問題はあっても誤差の問題は起こらなかったり。 | ||||||||||||||||||||
|
投稿日時: 2003-07-30 11:49
unibon です。こんにちわ。
一般論としては、そうだとうなずけます。
上記の「整数を表現」という言葉がどこまでを意味するのか分かりませんが、 もしも数値を変数に格納することならば、おっしゃるとおりです。 ただ、計算途中の値についてはその限りではないと思いますので、 以下に言及します。 あまり分かりやすい例ではないのですが、 四捨五入するやりかたとして、つぎの2つのやりかたを比較してみます。 #すみません、VBScript です。 適宜翻訳して読んでください。
たまたま VBScript では64ビット整数型がないこともあり、 64ビット整数型も64ビット浮動小数点型も使わずに整数型だけで演算しようとすると、 32ビット整数型までしか使えません。 こうすると引数が 2147433648 以上だと HeeRound の内部で演算途中にオーバフローが発生します。 こういう時にはビット数の多い64ビット浮動小数点型が使えるのならば "浮動小数点型の特質を知った上で"使うのは構わないと思います。 MyRound のほうは、入力が 2147450000 以上のときに 関数の戻り値がオーバフローすることはあります(これは四捨五入の定義上仕方がない)が、 演算途中でのオーバフローはありません。 #四捨五入の例だと、2147433648 以上のことなんて軽微なのであまり重要性はないかもしれませんが、 #他の変換だとたとえば上限が1桁少なくて 214748364(= 2147483648 / 10)以上が使えないとか、 #そう場面もチョクチョクありうると思います(うまい例が見つかりませんが)。 ただ、上記で書いた「浮動小数点型の特質を知った上で」という前提が、 結構難しいんですよね。これは否定できません。 多くのかたのご指摘もこれを危惧されてのことだろうと推測します。 ただ、こういう問題はプログラミングのロジックの話というよりは、 プログラミング標準やプロジェクト管理とかそっちの方で語るもののような気もします。 #明確に分離できるものとは限りませんが。 |