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

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

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

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

Q&A

解決済

4回答

9577閲覧

sqrt系関数の仕様について

退会済みユーザー

退会済みユーザー

総合スコア0

C

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

0グッド

1クリップ

投稿2018/09/21 08:26

編集2018/09/21 08:41

前提・実現したいこと

学習のためsqrt関数を使って平方根を求めています

sqrt関数は引数と戻り値がdouble型と調べると書いてあります。
また、sqrtf関数は引数と戻り値がfloat型と調べると書いてあります。

しかし、float型の引数、戻り値でsqrt関数を使っても出力結果が同じでした。(一つ目のコード)
また、double型の引数、戻り値でsqrtf関数を使い同じ処理を行いました。出力結果が同じです。(二つ目のコード)

なぜこのようなことが起きるのでしょうか・・・

一つ目のコードと結果

C

1 1 #include <stdio.h> 2 2 #include <math.h> 3 3 #define FLOATNUM 2.1 4 4 #define DOUBLENUM 2.1 5 5 6 6 int main(){ 7 7 float f = FLOATNUM; 8 8 double d = DOUBLENUM; 9 9 float fRoot; 10 10 double dRoot; 11 11 12 12 13 13 fRoot = sqrt( f ); 14 14 dRoot = sqrt ( d ); 15 15 16 16 17 17 printf("f = %f\n", f); 18 18 printf("fRoot = %f\n", fRoot); 19 19 printf("d = %f\n", d); 20 20 printf("dRoot = %f\n", dRoot); 21 21 22 22 } 23
f = 2.100000 fRoot = 1.449138 d = 2.100000 dRoot = 1.449138

二つ目のコード

C

1 1 #include <stdio.h> 2 2 #include <math.h> 3 3 #define FLOATNUM 2.1 4 4 #define DOUBLENUM 2.1 5 5 6 6 int main(){ 7 7 float f = FLOATNUM; 8 8 double d = DOUBLENUM; 9 9 float fRoot; 10 10 double dRoot; 11 11 12 12 13 13 fRoot = sqrtf( f ); 14 14 dRoot = sqrtf ( d ); 15 15 16 16 17 17 printf("f = %f\n", f); 18 18 printf("fRoot = %f\n", fRoot); 19 19 printf("d = %f\n", d); 20 20 printf("dRoot = %f\n", dRoot); 21 21 22 22 } 23
f = 2.100000 fRoot = 1.449138 d = 2.100000 dRoot = 1.449138

補足情報(FW/ツールのバージョンなど)

gcc でコンパイルしました。
Linuxです。ideone.comでも同じ結果だったのでコンパイルやOSの問題ではないのかと思います。

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

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

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

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

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

guest

回答4

0

C言語の場合、関数オーバロードがないので、float 精度で計算する場合は sqrtf()、double 精度で計算する場合は sqrt() を呼びます。

質問のコードはどちらも sqrt を読んでるので、double 型に暗黙的にキャストされて、sqrt(double) が呼ばれてます。

cpp

1#include <math.h> 2#include <stdio.h> 3 4int main() 5{ 6 float f = 2.1; 7 double d = 2.1; 8 printf("f: %.15f\n", f); 9 printf("d: %.15f\n", d); 10 11 float fRoot = sqrtf(f); 12 double dRoot = sqrt(d); 13 printf("fRoot: %.15f\n", fRoot); 14 printf("dRoot: %.15f\n", dRoot); 15} 16
f: 2.099999904632568 d: 2.100000000000000 fRoot: 1.449137687683105 dRoot: 1.449137674618944

float、double の精度

Wolframe Alpha で計算した正解

1.44913767461894385737186641571697717231401328747589730886959248071...
float: 1.4491376 8桁まで正解 double: 1.44913767461894 15桁まで正解

float はおおよそ7桁、double は 15桁程度の精度があるはずです。
(丸め誤差によりこれより精度が落ちることはありますが)

投稿2018/09/21 09:06

tiitoi

総合スコア21956

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

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

退会済みユーザー

退会済みユーザー

2018/09/21 09:10

とても丁寧な回答をしていただき、ありがとうございます! 先に回答して頂けたshowkit様をベストアンサーにしましたが本当に為になるご意見をして頂きありがとうございます!
guest

0

ベストアンサー

c

1 printf("f = %f\n", f); 2 printf("fRoot = %f\n", fRoot); 3 printf("d = %f\n", d); 4 printf("dRoot = %f\n", dRoot);

で出力しているからです。

c

1 printf("f = %f\n", f); 2 printf("fRoot = %.12f\n", fRoot); 3 printf("d = %f\n", d); 4 printf("dRoot = %.12f\n", dRoot);

で、もう一度やってみてください。
違う結果になるはずです。

投稿2018/09/21 08:40

showkit

総合スコア1638

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

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

退会済みユーザー

退会済みユーザー

2018/09/21 08:50

一つ目のコードのみ(sqrt関数のみ)出力結果に違いが出ました! 確かめですがsqrt関数はキャストして計算を行う関数ということですよね?
showkit

2018/09/21 08:58

C言語の仕様として より精度の近い方にキャストします。sqrt は倍精度なので、倍精度として計算します。sqrtf は 倍精度を与えても 返ってくる結果は float。 出力結果が違ったのは %f のみだと この場合 6桁になっちゃったので同じに見えますが 桁数を増やすと 精度の違いが出てくるということです。 参考↓ http://linuxjm.osdn.jp/html/LDP_man-pages/man3/sqrt.3.html
退会済みユーザー

退会済みユーザー

2018/09/21 09:06

ありがとうございます!
guest

0

C

1printf("dRoot = %f\n", dRoot);

この %f の指定が原因です。
%f で精度(小数点以下の桁数)を指定しない場合、6 が指定されたと見なされるため、小数点以下6桁までしか出てきません。

なので showkit さんの回答にもあるように、

C

1printf("dRoot = %.12f\n", dRoot);

と、小数点以下の桁数を指定する必要があります。

そうすると、

fRoot = 1.449138 dRoot = 1.449137674619

と、結果が違うことが分かります。

投稿2018/09/21 09:14

tacsheaven

総合スコア13703

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

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

退会済みユーザー

退会済みユーザー

2018/09/23 09:58

回答していただきありがとうございます。
guest

0

doubleとfloatって大体同じみたいです。厳密には違いますが、範囲が狭い・広いとか精密・おおざっぱ ぐらいの差らしいです。intとdoubleみたいな差ではなくて、intとlongぐらいの差(も無いとは思うが)ぐらいらしいです。

投稿2018/09/21 08:32

BeatStar

総合スコア4958

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

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

退会済みユーザー

退会済みユーザー

2018/09/21 08:40

変数の型が大体同じ... 感覚としてはわかりますが...他の関数でも同じようなことは起きるということですかね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問