質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

5回答

7694閲覧

10桁以上の計算結果が全て10桁になってしまう

opyon

総合スコア1009

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

0クリップ

投稿2018/08/03 06:44

編集2018/08/04 01:55

前提・実現したいこと

10桁以上の計算結果を可能な限り正しく出力したい。

発生している問題・エラーメッセージ

コードの1行目の数値で開始と終了を指定した整数の範囲の階乗の結果が表示されますが全て10桁になる  (10, 14) 10~14までの階乗を出力する 12! = 479001600 13! = 1932053504 14! = 1278945280

該当のソースコード

IntStream.rangeClosed(10, 14) .forEach(i -> { int kaijo = IntStream.rangeClosed(1, i).reduce(1, (i1, i2) -> i1 * i2); System.out.println(i + "! = " + kaijo); });

試したこと

変数の型をint型からdouble型に変えたが結果変わらず
print関連のjavadocを読んでみたりネットで桁数関連の検索をしてみたのですが解決には至りませんでした。

恐らく13!までは正常に表示されていて14!から桁が足りていないのではないかと思います。
何かしらの仕様だとは思うのですが何故このような表示になるのか理由と解決策があれば知りたいです。

参考までに追記と感想

回答頂いた中から参考にさせていただきfor文で書いたところ、意外とあっさり動いていまいました。
streamはとても便利だと思うのですが理解度が足りず、自分で変更などしようとすると思い通りにならず苦労します。
頂いた回答を元に色々と触って精進したいと思います。

Java

1for (int i = 10; i <= 20; i++) { 2 BigInteger kaijo = BigInteger.valueOf(1); 3 for (int j = 1; j <= i; j++) { 4 kaijo = (kaijo).multiply(BigInteger.valueOf(j)); 5 } 6 System.out.println(i + "! = " + kaijo); 7} 8

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sysjojo

2018/08/03 06:54 編集

変えたコードや検索して参考にしたページも載せるとよいですよ。変えた後、IntStream残ってたりしません?
opyon

2018/08/04 01:28

すみません このコメントに気づきませんでした。投稿した時点ではIntStream自体意味がわかっていませんでしたのでint kaijoをdouble kaijoに変えた程度です。
guest

回答5

0

既に解決済みですが、他の方法が一応あるのでそちらの紹介をします。

例えば、50!を求めたいときint,longだとオーバーフローしてしまうのですが、
javaには大きな数値を計算するために「BigIntegerクラス」が存在します。
(ちなみにより正確な小数を求めるために「BigDecimalクラス」というものもあります。)

これらを利用して計算するときは+,-,*,/などの記号は利用できません
詳しくはBigInteger,BigDecimalの使い方をご覧ください。

java

1import java.util.*; 2import java.math.BigInteger; 3 4public class Main { 5 public static void main(String[] args) { 6 7 Scanner sc = new Scanner(System.in); 8 int n = sc.nextInt(); 9 10 fact(n); 11 } 12 13 public static void fact(int n) 14 { 15 BigInteger sum = new BigInteger("1"); 16 for (int i = 2; i <= n; i++) { 17 sum = sum.multiply(new BigInteger(String.valueOf(i))); 18 } 19 System.out.println(n + "! = " + sum); 20 } 21}

<実行例>
50 ! = 30414093201713378043612608166064768844377641568960512000000000000

投稿2018/08/03 09:28

編集2018/08/03 09:28
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2018/08/03 12:26

なぜに低評価?
退会済みユーザー

退会済みユーザー

2018/08/03 12:29

@swordoneさんへ 高評価ありがとうございます。
退会済みユーザー

退会済みユーザー

2018/08/03 12:33 編集

低評価された理由がいまいちわからないので低評価した方、理由を書いてくださると助かります。
退会済みユーザー

退会済みユーザー

2018/08/03 12:30

どこか不備があるなら直すので
opyon

2018/08/03 20:26

ありがとうございます 階乗を求める、桁数が多い、シンプル、 全てにおいて洗練されたコードでとても勉強になりました。
guest

0

ちなみに

変数の型をint型からdouble型に変えたが結果変わらず

計算しようとしている数値の型がintなので、intのオーバーフローの問題は避けられません。
(intの計算結果であるintを後からdoubleにキャストしている格好となる)

doubleで計算させたいのならば、DoubleStreamにして計算しましょう。

java

1 IntStream.rangeClosed(10, 14) 2 .forEach(i -> { 3 double kaijo = IntStream.rangeClosed(1, i) 4 .asDoubleStream() 5 .reduce(1.0, (i1, i2) -> i1 * i2); 6 System.out.println(i + "! = " + kaijo); 7 });

投稿2018/08/03 07:49

編集2018/08/04 12:34
swordone

総合スコア20669

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/08/03 08:23

ありがとうございます 15:56に回答がありましたのでそちらの方へ ベストアンサーとさせていただきました。
opyon

2018/08/04 00:26 編集

せっかく頂いたコードですが当方の環境ではこのままだとエラーが出ています。 エラー内容: kaijo を変数に解決できません このコードだと末尾の kaijo に値が代入されて無いのでしょうか? 色々触ってみましたが自力では解決出来ないのですが 別件になるのでここではコメントだけとさせていただいております。
swordone

2018/08/04 00:55

すみません。階乗の元と結果を表示するという目的を忘れ、mapで変換してしまいました。 forEachに直します。
opyon

2018/08/04 01:38

ありがとうございます int kaijo = を double kaijo = にすることで double 型 での出力が出来ました 20! = 2.43290200817664E18 1つの質問で色々な回答頂いており自分であれこれ試行錯誤することでとても勉強になります
guest

0

参考情報

  • forやifで書くアレをStream APIで書く

http://masatoshitada.hatenadiary.jp/entry/2014/10/10/123910

  • 100の階乗を計算するプログラムを書いてみた

http://yng.hatenablog.jp/entry/2015/05/12/004048

  • 【Java】1000000!のような巨大な階乗計算をする [任意精度整数(多倍長整数)]

http://fantom1x.blog130.fc2.com/blog-entry-198.html

  • Problem 20 100!の各桁の合計を求めよ。

http://java-beginner.com/project-euler-java-16-20/

投稿2018/08/04 08:20

katoy

総合スコア22324

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/08/04 09:17

参考情報ありがとうございます 1番上のurlは正にこの質問の元になったコードです。 そこのコードで練習していて質問しました。 その他リンクも参考にして精進したいと思います。
katoy

2018/08/04 13:01

何万桁も円周率を計算する方法も考えてみる(調査/検索) してみると良いです。 整数部の桁数が長くなるのと、小数部が長くなるのとは 何が似ていて何が違うのか? 循環少数 (1/3 = 0.33333....) に 3 を書けたら 1 になるようにするにはどうしたらよいのかも考えてみてください。
opyon

2018/08/05 02:25

ありがとうございます 課題にしてみたいと思います
opyon

2018/08/05 03:06

少し調べてみましたが自分の今のレベルでは理解するのに相当な時間がかかりそうなので保留として 解けそうな課題から少しづつ練習してみます
guest

0

Streamを使ったまま、BigIntegerで(メモリが許す限り)何桁でもできる書き方を一応書いておきます。

Java

1 IntStream.rangeClosed(10, 50) 2 .forEach(i -> { 3 BigInteger kaijo = IntStream.rangeClosed(1, i) 4 .mapToObj(BigInteger::valueOf) 5 .reduce(BigInteger.valueOf(1), (i1, i2) -> i1.multiply(i2)); 6 System.out.println(i + "! = " + kaijo); 7 });

投稿2018/08/03 23:25

raccy

総合スコア21739

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/08/04 00:20

ありがとうございます streamでワンライナーでサラッと書けるなんて羨ましいです 自分で白紙から書くとエラーが出まくって焦ります 1つの質問でこれだけ回答が来ると思っていなかったので驚きです みなさんから頂いた回答を1つ1つ実行させたり少し変更したり とてもよい教材になってます
guest

0

ベストアンサー

提示のコードをlongLongStreamに置き換えた所、正常に動作しました(paiza.ioでの動作結果)。

java

1 LongStream.rangeClosed(10, 14) 2 .forEach(i -> { 3 long kaijo = LongStream.rangeClosed(1, i).reduce(1, (i1, i2) -> i1 * i2); 4 System.out.println(i + "! = " + kaijo); 5 });

ただし、longでも符号付き64ビットしかないので、計算を進めればあふれるポイントは来ます。

投稿2018/08/03 06:56

maisumakun

総合スコア146050

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

opyon

2018/08/03 07:01

ネットで見つけたコードで理屈もわからないままでしたが勉強になりました。 ありがとうございました
opyon

2018/08/03 07:03

10! = 3628800 11! = 39916800 12! = 479001600 13! = 6227020800 14! = 87178291200 15! = 1307674368000 16! = 20922789888000 17! = 355687428096000 18! = 6402373705728000 19! = 121645100408832000 20! = 2432902008176640000
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問