Javaで自作の四捨五入メソッドを実装する方法

このQ&Aのポイント
  • Javaで自作の四捨五入メソッドを実装する方法を紹介します。Math.round()のように小数点以下を四捨五入するメソッドを作りたい場合、数学的な処理を使って小数点以下を判別し、四捨五入の結果を返すことができます。
  • 現在の自作のメソッドはintで型キャストする方法を使っていますが、数学的な処理を使うことでより正確な結果を得ることができます。
  • 使用例として、2.4、2.5、-2.4、-2.5、4.5の値を四捨五入して出力するプログラムを紹介します。出力結果は2.4 → 2、2.5 → 3、-2.4 → -2、-2.5 → -3、4.5 → 5です。
回答を見る
  • ベストアンサー

四捨五入をするメソッドを実装したい(Java)

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 です。 */

  • Java
  • 回答数6
  • ありがとう数9

質問者が選んだベストアンサー

  • ベストアンサー
  • kmee
  • ベストアンサー率55% (1857/3366)
回答No.3

面白そうなので、ソースコードを追い掛けてみました。 OpenJDKのものですが、これを見ると、Math.round等は、StrictMathへのラッパーになってます。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/lang/Math.java StrictMathについては、以下に説明があります。 http://docs.oracle.com/javase/jp/6/api/java/lang/StrictMath.html roundについては http://docs.oracle.com/javase/jp/6/api/java/lang/StrictMath.html#round%28double%29 そこにあった「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 の整数部だけ残すようにビットシフトする  はみ出た分(=小数部)は削られるので、整数化される という方法が取られています。

newtgecko
質問者

お礼

質問を「round()の中身が見たい!」っていえば質問がわかりやすかったような気がしています... ご回答ありがとうございます。 リンクすごくためになります。見たいもの色々と見れて、round以外もみたいです。お気に入りにしました☆ >これによれば。(省略します) 説明があって助かります。 Cの知らない所ばかりで書かれていて、ほとんど読めないので助かりました。 用意されているメソッドは効率よく作られているイメージがあるので、ビットレベル(?)で操作しているような気はしていました。小数をどのように管理しているかの仕組みを勉強してから、戻ってきます。 ありがとうございました。

newtgecko
質問者

補足

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

その他の回答 (5)

  • foomufoomu
  • ベストアンサー率36% (1018/2761)
回答No.6

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

newtgecko
質問者

お礼

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

newtgecko
質問者

補足

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

  • foomufoomu
  • ベストアンサー率36% (1018/2761)
回答No.5

余計なことかもしれませんが、前に書いた、 >丸める数がきっちり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) とすればできます。

newtgecko
質問者

お礼

親身にご回答ありがとうございます。 「丸める」という言葉にあまり馴染みがなかったですが、文字のイメージからわかります。 >事務系などでは(2)を使うこともあるようです。 普通の四捨五入(算数でする)のイメージは個人的には(2)のような気がするのですが... 確認させてください。 (2)の方法では、 2.4 → 2.0 2.5 → 3.0 -2.4 → -2.0 ですよね?

newtgecko
質問者

補足

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

  • oooioi
  • ベストアンサー率29% (16/55)
回答No.4

たぶん一番手っ取り早いのは 目的の数値に対して0.5を足してその足した値に対してint型にキャストして少数以下を切り捨てる。

newtgecko
質問者

お礼

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

newtgecko
質問者

補足

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

  • foomufoomu
  • ベストアンサー率36% (1018/2761)
回答No.2

四捨五入なら、ごく普通に使われている丸め式を使えばよいです。 たとえば、ここのroundの解説を見てください。 http://www.javadrive.jp/start/math/index7.html 丸める数がきっちり0.5の時の扱いは、つごう3通りのやり方がある(それぞれ結果が違う)のですが、細かいことを言わなければ、前記の式で無問題

newtgecko
質問者

お礼

ご回答ありがとうございます。 >丸める数がきっちり0.5の時の扱いは、つごう3通りのやり方がある(それぞれ結果が違う)のですが、細かいことを言わなければ、前記の式で無問題 そのとおりなんですけど。 少しアルゴリズム的な問題で、どのようにすれば、自分でround()のようなメソッドを作ることができるかな?ということを考えたかったのです。 どうしても小数点以下を取り出す計算式を考えつくことができなかったので、質問させていただきました。

  • askaaska
  • ベストアンサー率35% (1455/4149)
回答No.1

いきなり四捨五入するメソッドを作らずに まず、小数点位下を切り捨てるメソッドを作れば キャストしなくて済むんじゃない?

newtgecko
質問者

お礼

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

関連するQ&A

  • 四捨五入について

    とあるテキストに、3.848を四捨五入して小数点第一位まで求めると、3.8になる、と書いてあります。しかし、3.848の小数点第三位の8を四捨五入すると、3.85になり、これを更に四捨五入すると、3.9になるように思うのですが、いかがでしょうか?

  • 四捨五入関数を作りたい

    Cでdouble型の数値の四捨五入を考えています。 小数点7桁目を四捨五入したいです。 1000000倍して0.5足して切り捨てる やり方が載っていました。 しかし1000000倍した時に誤差で「.3999999」となる ことがあるようです。 どうやったら回避できるのでしょうか。

  • 四捨五入について

    "1.005"を小数点第三位で四捨五入して、"1.01"にしたいのですが、 "Math.round(1.005*100)/100"だと1.005*100が100.4999999999998になってしまい、結果的に"1.00"が返されてしまいます。何か良い解決方法はないでしょうか?

  • 四捨五入、簡単そうで、出来ません・・・

    お世話になります。 さて、 18643.52 この数字を、まず、小数点を四捨五入して 18644 とします。 次に、 18644の数字を、四捨五入して、 18640 としたいです。 一気に、18643.52 から 18640 とする方法は ありますか? 教えて下さい。

  • 四捨五入、丸め・・・?

    たとえば、235.4を小数点第一位で「四捨五入」すると、236ですよね。 334を330に、336を340にするような場合は、なにか言い方がありますか? わかりにくくてすみません。

  • 四捨五入

    小数点以下を四捨五入するとして、「-1.5」は「-1」なのか「-2」なのかどちらなのでしょうか?

  • 小数第1位を四捨五入

    ちょっと混乱してしまったので質問させてください。 エクセルの関数の練習問題集をやってまして、その中で 「小数第1位を四捨五入する」 「小数第1位を切り上げる」 という表現が出てくるのですが、これの答えは小数第1位までの数字になりますか? それとも、小数点なしの数字になりますか? たとえば1.562という数字ならば、上記の四捨五入の場合答えは2になりますか? それとも1.6でしょうか? 学校で数学を習ったのがかなり昔なので、表現がわからなくなりました(^_^;)

  • 四捨五入について質問があります

    割合0.5135を小数点以下第一位に四捨五入すると、51%になるみたいなのですが、この時小数第一位である5を四捨五入すると思うのですが、何故51%になるのでしょうか?5は繰り上がって一の位に行くと思うのですが、、

  • 四捨五入でどこから切り上げるか質問です

    四捨五入で質問です 下記の様な数字の場合 ≒1.444444445 小数点第二位までの四捨五入の場合、 1.45 だと思うのです それとも、小数点第三位のみから考え、 1.44 となりますか? 年の瀬皆様お忙しいところ大変恐縮です 何卒よろしくお願いいたします

  • VC++で四捨五入

    こんにちは。 Microsoft Visual C++ 2003.NETで、Windowsフォームアプリケーションを作っています。 そこで、ある計算をさせて、答えをdouble型の変数に入れたのですが、答えが「0.99999...」や「1.548932...」のように、延々となってしまいます。かといってint型にすると、小数を扱えないので… 出来れば小数第三位くらいで四捨五入したいのですが、VC++にはそのような際に便利な関数はあるのでしょうか? 初歩的な質問で申し訳ありませんが、よろしくお願いします。