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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

3回答

1272閲覧

1/(5^n) の結果をすべて表示させるプログラムを作りたい

Taka787

総合スコア23

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

2クリップ

投稿2019/05/28 08:43

編集2019/05/28 08:46

前提・実現したいこと

長文失礼します。

標準入力から与えられた正整数 n ( 0<n<9900 ) に対して、 1/(5^n) の小数表示を標準出力に書き出すプログラムを作っています。 1/(5^n) は有限小数になります。 その有限小数を十進表現で左詰にで1行にして標準出力に書き出したいと思っています。
しかし、実行すると想定している値とは違う値が出ます。
以下の求めたい出力結果にするにはどう訂正すればよいでしょうか?

発生している問題・実行結果

標準入力:1 標準出力:0.200000 標準入力:2 標準出力:0.040000 標準入力:5 標準出力:0.000320 標準入力:10 標準出力:0.000000 標準入力:16 標準出力:0.000000 標準入力:100 標準出力:0.000000 標準入力:4096 標準出力:0.000000

該当のソースコード

c

1#include <stdio.h> 2#include <float.h> 3 4int main(int argc, char *argv[]){ 5 int n, i; 6 unsigned long long int x = 1; 7 8 scanf("%d", &n); 9 10 double ans; 11 12 for(i=1; i<=n; i++){ 13 x*=5; 14 } 15 16 ans = (double)1 / x; 17 18 printf("%lf\n", ans); 19 20 return 0; 21}

求めたい出力結果

標準入力:1 標準出力:0.2 標準入力:2 標準出力:0.04 標準入力:5 標準出力:0.00032 標準入力:10 標準出力:0.0000001024 標準入力:16 標準出力:0.0000000000065536 標準入力:100 標準出力:0.0000000000000000000000000000000000000000000000000000000000000000000001267650600228229401496703205376 標準入力:4096 標準出力:0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001044388881413152506691752710716624382579964249047383780384233483283953907971557456848826811934997558340890106714439262837987573438185793607263236087851365277945956976543709998340361590134383718314428070011855946226376318839397712745672334684344586617496807908705803704071284048740118609114467977783598029006686938976881787785946905630190260940599579453432823469303026696443059025015972399867714215541693835559885291486318237914434496734087811872639496475100189041349008417061675093668333850551032972088269550769983616369411933015213796825837188091833656751221318492846368125550225998300412344784862595674492194617023806505913245610825731835380087608622102834270197698202313169017678006675195485079921636419370285375124784014907159135459982790513399611551794271106831134090584272884279791554849782954323534517065223269061394905987693002122963395687782878948440616007412945674919823050571642377154816321380631045902916136926708342856440730447899971901781465763473223850267253059899795996090799469201774624817718449867455659250178329070473119433165550807568221846571746373296884912819520317457002440926616910874148385078411929804522981857338977648103126085903001302413467189726673216491511131602920781738033436090243804708340403154190336

補足情報

試したこととして、標準出力の時に%lfではなく、%gに変更するとすべての小数を表示できると書いてあったので試しましたが駄目でした。

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

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

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

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

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

guest

回答3

0

まず、一般的なC言語環境では、doubleの精度は16桁弱しかありません。5**(-9900)を表示させるには、全く足りません。

そして、5**-n = 2**n / 10**nなので、2の累乗を計算して桁をずらせば5のマイナスの累乗を作れます。ただし、これまた2**9900は3000桁弱の数となりますので、普通に計算しては桁が足りません。多倍長演算を行う必要があります。

投稿2019/05/28 08:52

maisumakun

総合スコア145183

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

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

Taka787

2019/05/28 09:56 編集

``` #include <stdio.h> #include <float.h> int main(int argc, char *argv[]){ int n, i, j, t; unsigned long long int x = 1; scanf("%d", &n); printf("0."); for(i=1; i<=n; i++){ x*=5; } int ans[5000] = {0}; for(j=0; j<5000; j++){ ans[j] = 1 / x; x = 1 % x; } for(t=0; t<5000; t++){ printf("%d", ans[t]); } return 0; } ```
Taka787

2019/05/28 09:57

こんな感じで訂正してみました。 配列に計算した答えを入れて表示させようとしました。
Taka787

2019/05/28 09:58

すると何も表示されないのですがどうしてでしょうか?
maisumakun

2019/05/28 10:33

long longでもたいてい64ビットなので、ぜんぜん足りないです。自力で(あるいは相応のライブラリを使って)もっと大きな桁数の計算を行う必要があります。
Taka787

2019/05/28 22:59

もう少し考えてみます。
guest

0

printfのフォーマット文字列で出力する桁数を設定しましょう

投稿2019/05/28 08:50

y_waiwai

総合スコア87749

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

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

maisumakun

2019/05/28 08:53

ふつうのdoubleでは、精度が全く足りません。
y_waiwai

2019/05/28 08:58

まあ、なにを問題としてるか、ってはなしで。 私は、出力してる桁数が足りないと言っている、とみましたねw 精度が足りないってのはそのとおりなんだけど、それはべつのおはなしってことで。
Zuishin

2019/05/28 10:36

精度が足りないと求めたい出力結果が得られないので別じゃないはずです。
y_waiwai

2019/05/28 10:48

精度が足りても解決しませんわな。どうしましょうか
Zuishin

2019/05/28 10:54

maisumakun さんの回答のように多倍長演算を行って文字列に直すのが一番素直な解法じゃないですか? 計算式と値の範囲が決まっているので私なら手抜きをして文字列で直接計算するかもしれません。
y_waiwai

2019/05/28 11:00

まあ、実のところ、あのコードではansの精度よりも、xのほうが先に限界迎えますな
Zuishin

2019/05/28 11:03

つまりこの回答は正しい回答ということですか? それとも正しくない理由が増えたということですか?
y_waiwai

2019/05/28 11:07

どちらも正しいし、どちらも間違ってるってところじゃないかと。 まあ、そもそもの設問がムリゲーなわけですが。
Zuishin

2019/05/28 11:12 編集

いや全然ムリゲーじゃありません。解くことの可能な問題です。Paiza だと B ランクくらいじゃないですか? 課題っぽいので書きませんが。
y_waiwai

2019/05/28 11:15

そりゃ可能か不可能か、といえば可能でしょう。 ましかし、5^9900って時点でどうやって検証するんやこれってはなしなわけでw
maisumakun

2019/05/28 11:18

とはいえ、C縛りでなかったら、自分としては多倍長整数も有理数も組み込みで存在するRubyで書きたいです(そういう言語を使えば、Cで作った結果の検証も容易かと思います)。
Zuishin

2019/05/28 11:31

5 の累乗は計算する必要ありませんよ。見ての通り 2 の累乗の頭に 0 を並べた結果になるので。
y_waiwai

2019/05/28 11:36

そういうところで向き不向きの言語ってのがでてきますねー Cでやるとなると演算ルーチンから構築していかんとあかんわけで。 おもしろいですね
Taka787

2019/05/28 23:01

自分にとっては結構難しいですが、解決すればまた一つ勉強にもなるので、解決に向けて奮闘中です。 皆様、いろいろな回答ありがとうございます。
sage

2019/06/07 08:45

9899が指定された場合、桁数はいくつになって、どういうフォーマット文字列で桁数を指定するのですか?
guest

0

C

1#include <stdio.h> 2 3int main(void) 4{ 5 int n, i, j, k, c, a[9900]; 6 while (scanf("%d", &n) == 1 && n > 0 && n < 9900) { 7 for (a[0] = k = 1, i = 0; i < n; i++) { 8 for (c = j = 0; j < k; j++) { 9 a[j] = a[j] * 2 + c; 10 if (c = a[j] >= 10) a[j] -= 10; 11 } 12 if (c) a[k++] = 1; 13 } 14 printf("0.%0*s", n - k, ""); 15 while (--k >= 0) putchar(a[k] + '0'); 16 putchar('\n'); 17 } 18}

1/(5^n) = (2^n)/(10^n)
すなわち 2のn乗の小数点を n桁ずらしたものです。
n < 9900 なら、int a[9900] は char a[2980] で十分です。

投稿2019/06/06 18:56

編集2019/06/07 02:19
kazuma-s

総合スコア8224

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

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

sage

2019/06/07 08:39 編集

どういう環境だとこれでうまくいくのでしょうか? CentOS7のgccだと小数点以下の0が表示されず 5 0. 32 のようになります。( 「.」と「3」の間に空白が3つ)
kazuma-s

2019/06/07 09:11

Visual C++ と Cygwin の gcc では問題なかったのですが、 今、Ubuntu の gcc で試したら、 printf の "%s" に 0フラグは使えないという警告が出ました。 printf の行を次のように修正してください。 printf("0."); for (n -= k; --n >= 0; ) putchar('0');
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問