dポイントプレゼントキャンペーン実施中!

Math.round()のように小数点以下を四捨五入するメソッド作りたいです。
できれば、数値計算(数学的に?)で実数を処理したいです。

自分で作れたのはintで型キャストするやり方で、あまり納得していません。
うまく数学的な処理で小数点以下を判別して、四捨五入の結果を返すことはできませんか?

ちなみに自作したものはこんなかんじです↓。

public class MyRoundTest {
   // 四捨五入
   static int myRound(double d){
      int sign = (d < 0) ? -1 : 1;
      double mid = (int)(d)+sign*0.5;
      return (d*sign >= mid*sign)? (int)d+sign: (int)d;
   }

   public static void main(String[] args){
      double[] d = {2.4, 2.5, -2.4, -2.5, 4.5};

      for(double element : d){
         System.out.println(element+"\t→\t"+myRound(element));
      }

   }

}

/*
出力結果は

2.4→2
2.5→3
-2.4→-2
-2.5→-3
4.5→5
です。
*/

A 回答 (6件)

面白そうなので、ソースコードを追い掛けてみました。



OpenJDKのものですが、これを見ると、Math.round等は、StrictMathへのラッパーになってます。
http://grepcode.com/file/repository.grepcode.com …

StrictMathについては、以下に説明があります。
http://docs.oracle.com/javase/jp/6/api/java/lang …
roundについては
http://docs.oracle.com/javase/jp/6/api/java/lang …

そこにあった「Freely Distributable Math Library」から、floorのソースコードを見ます。
http://www.netlib.org/fdlibm/s_floor.c

これによれば。
・浮動小数点数の内部形式に直接アクセスして、 指数と仮数を得る。
  浮動小数点数は、 符号(+1または-1) * a * 2^n (1.0<= a < 2.0 )の形式になっている
・a * 2^n の整数部だけ残すようにビットシフトする
 はみ出た分(=小数部)は削られるので、整数化される
という方法が取られています。

この回答への補足

回答をくださった皆様、お返事に時間が開いてしまいました。すみません。

補足日時:2013/08/30 09:15
    • good
    • 0
この回答へのお礼

質問を「round()の中身が見たい!」っていえば質問がわかりやすかったような気がしています...

ご回答ありがとうございます。
リンクすごくためになります。見たいもの色々と見れて、round以外もみたいです。お気に入りにしました☆

>これによれば。(省略します)
説明があって助かります。
Cの知らない所ばかりで書かれていて、ほとんど読めないので助かりました。
用意されているメソッドは効率よく作られているイメージがあるので、ビットレベル(?)で操作しているような気はしていました。小数をどのように管理しているかの仕組みを勉強してから、戻ってきます。

ありがとうございました。

お礼日時:2013/08/30 09:15

あ、もしかして、


>そのとおりなんですけど。
というのは、「roundを使え」という意味だと思ったのですか?

リンク先を見ればわかりますが、roundの解説に、次の式が書いてあります。
Math.floor(a + 0.5)
これが直前に書いた(1)の丸め方の、もっともありふれた数学的(?)な表現です。
(リンク先には(2)の丸め方ととれるような書き方になっていますが、正しくは(1)の丸め方です)

この回答への補足

回答をくださった皆様、お返事に時間が開いてしまいました。すみません。

補足日時:2013/08/30 09:29
    • good
    • 0
この回答へのお礼

>というのは、「roundを使え」という意味だと思ったのですか?
そう思ってしまいました。ごめんなさい。

この質問をした理由になるのですが、
(同じ内容が他のお礼と重複してしまいます)
なるべく最初から、round()メソッドを作ってみたかったということです。
既存の仕組みに頼ることなく(型キャストやメソッド)、何らかの式(四則演算で表せるような)でround()を実装してみたかったということです。

お礼日時:2013/08/30 09:35

余計なことかもしれませんが、前に書いた、


>丸める数がきっちり0.5の時の扱いは、つごう3通りのやり方がある(それぞれ結果が違う)のですが、
について説明しておきます。

まず、これは、少数点以下の部分がきっちり0.5の時(0.5000000・・・)に限った話です。
で、3通りのやり方というのは、
(1) 常に+∞方向に丸める。-3.5は-3になる。
(2) 常に0から遠ざかる方向に丸める。-3.5は-4になる。
(3) JISの丸め規則に従った丸め方で、丸めた数が偶数になるように丸める。-3.5は-4に、-2.5は-2になる。

一番誤差が少なくなるのは(3)の丸め方ですが、通常は(1)の丸め方を使います。何のメリットがあるのか分かりませんが、事務系などでは(2)を使うこともあるようです。
前の解答で書いたリンクの方法では(1)の丸め方になります。

(3)のJIS丸めをしたい場合は。
(d-Math.floor(d))=0.5 ? Math.floor(d/2+0.5)*2 : Math.floor(d+0.5)
となります。
ちなみに(2)のまるめは
d >= 0 ? Math.floor(d+0.5) : Math.ceil(d-0.5)
とすればできます。

この回答への補足

回答をくださった皆様、お返事に時間が開いてしまいました。すみません。

補足日時:2013/08/30 09:23
    • good
    • 0
この回答へのお礼

親身にご回答ありがとうございます。

「丸める」という言葉にあまり馴染みがなかったですが、文字のイメージからわかります。

>事務系などでは(2)を使うこともあるようです。
普通の四捨五入(算数でする)のイメージは個人的には(2)のような気がするのですが...

確認させてください。
(2)の方法では、
2.4 → 2.0
2.5 → 3.0
-2.4 → -2.0
ですよね?

お礼日時:2013/08/30 09:29

たぶん一番手っ取り早いのは


目的の数値に対して0.5を足してその足した値に対してint型にキャストして少数以下を切り捨てる。

この回答への補足

回答をくださった皆様、お返事に時間が開いてしまいました。すみません。

補足日時:2013/08/30 09:16
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

なるべくなら、型キャストを使いたくなかったのです。
理由はなるべく自分で最初から作りたかったからです。既存の仕組みに頼らず、
小数点以下を切り捨てる仕組みを元に帰れば、「四則演算+剰余」ぐらいで作ってみたかったということです。

お礼日時:2013/08/30 09:20

四捨五入なら、ごく普通に使われている丸め式を使えばよいです。


たとえば、ここのroundの解説を見てください。
http://www.javadrive.jp/start/math/index7.html

丸める数がきっちり0.5の時の扱いは、つごう3通りのやり方がある(それぞれ結果が違う)のですが、細かいことを言わなければ、前記の式で無問題
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>丸める数がきっちり0.5の時の扱いは、つごう3通りのやり方がある(それぞれ結果が違う)のですが、細かいことを言わなければ、前記の式で無問題

そのとおりなんですけど。
少しアルゴリズム的な問題で、どのようにすれば、自分でround()のようなメソッドを作ることができるかな?ということを考えたかったのです。
どうしても小数点以下を取り出す計算式を考えつくことができなかったので、質問させていただきました。

お礼日時:2013/08/27 15:56

いきなり四捨五入するメソッドを作らずに


まず、小数点位下を切り捨てるメソッドを作れば
キャストしなくて済むんじゃない?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

>小数点位下を切り捨てるメソッドを作れば...
そうなんですよね。
小数点以下を切り捨てる方法がわかれば、小数点部分だけ取り出すことができて、それを >= 0.5 などで比較すれば、四捨五入がですけど... 切り捨てる方法が思いつかないのです。ceil()などには頼らず、全て+ - * / % などで処理したいのです。

お礼日時:2013/08/27 15:42

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!