C言語である計算を一億回したときの計算時間について調べています。

sinやcosなどの初等関数の計算は、足し算や引き算などの四則演算に比べ、計算時間がかかるのは何故ですか?

このQ&Aに関連する最新のQ&A

A 回答 (1件)

加減乗除などは、基礎的な演算なので、CPUはかなり早く計算することができます。



sinやcosなどの関数は、
CPU内部で級数展開によって計算されます。
たとえば
sin x = x - x^3/3! + x^5/5! - x^7/7! +.....
という具合。これを十分な精度が出るまで繰り返して値を出します。
加減乗除のステップがいくつも含まれているので、
時間がかかるのです。
    • good
    • 0
この回答へのお礼

ありがとうございます。

お礼日時:2005/04/19 15:00

このQ&Aに関連する人気のQ&A

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

このQ&Aと関連する良く見られている質問

Qエクセルのマクロないでの三角関数計算

エクセルのマクロ内で三角関数の計算をしたいのですが、マクロ内での度→ラジアンの変換が上手くできずにいきづまってしまいました。

なにか良い方法をご教示お願いします。

Aベストアンサー

こんにちは。

本来は、基礎の基礎のようですね。

マクロでは、こんな感じで使います。

Const PI As Double = 3.14159265

 x = Cos(60 * PI / 180)
 y = -Sin(60 * PI / 180)

Q数値計算の高速化 (cos, sin, exp)

数値計算の計算コストに関しての質問です。

webなどで見ていると、「cos, sin, expは計算コストが
高く、高速化のために、他の計算方法で代用できる
場合は代用する」ということが書かれていたのを見ました。

cosやsinの計算にテイラー展開したもので代用する方が
計算が早くなるということでしょうか?

Aベストアンサー

★乗算はテーブルにすると早い。
・2桁の『乗算』を『*』演算子で計算するよりも、10×10 のテーブルを
 用意して、テーブル参照させると高速になります。また、1桁の参照も
 別の1桁テーブル参照をさせると高速になります。→組み合わせる。
・このようにテーブルを用意して、固定小数点(整数値)で計算させると
 高速になります。→『多倍長演算』と呼び、マクローリン展開でどこ
 まで計算結果に精度を求めるかです。
・『マクローリン展開』でも収束するまで計算させるのではなく、回数を
 指定して 3~4 で強制的に計算を終了すれば高速になります。
・収束は倍・倍に精度がよくなるため、3~4 回の計算でも結構よい精度
 になりそうです。→試してみましょう。

最後に:
・よく使う数は、『定数』としてテーブルに保存して計算させると高速化
 できます。→『マクローリン展開』で利用する『階乗』など。(1!~6!)
・あと、実数値を多倍長の整数値で表現して、あとで小数点と桁数の丸め
 込みなどを行えば高速になります。→実数よりも整数が高速だから。
・『多倍長演算』で検索するといろいろ出てきます。
・以上。おわり。参考になりましたか?

リンク:
・http://yosshy.sansu.org/maclaurin.htm
・http://assam.cims.hokudai.ac.jp/~josch/workshop/math/Maclaurin/Maclaurin1.htm
・http://www.sist.ac.jp/~suganuma/kougi/other_lecture/SE/math/diff/diff.htm

参考URL:http://www5.airnet.ne.jp/tomy/cpro/longint.htm

★乗算はテーブルにすると早い。
・2桁の『乗算』を『*』演算子で計算するよりも、10×10 のテーブルを
 用意して、テーブル参照させると高速になります。また、1桁の参照も
 別の1桁テーブル参照をさせると高速になります。→組み合わせる。
・このようにテーブルを用意して、固定小数点(整数値)で計算させると
 高速になります。→『多倍長演算』と呼び、マクローリン展開でどこ
 まで計算結果に精度を求めるかです。
・『マクローリン展開』でも収束するまで計算させるのではなく、回数を
 指定して 3...続きを読む

Q今日は、Vista電卓で三角関数の計算を教えて下さい。ポケットサイズの

今日は、Vista電卓で三角関数の計算を教えて下さい。ポケットサイズの計算機で関数の計算をする時、例えば、直角三角形の斜辺と角度(A,B,Cの時、角Aが60°として斜辺は、2です)が与えられる時、対辺と燐辺はsin,cosで求められますよね、ポケットサイズの計算機では2×sin60°対辺 2×cos60、燐辺が計算出来ますよね、Windows Vista電卓では、どうするのですか???パソコン初心者の私に教えて下さい。

Aベストアンサー

ヘルプ読めば出てませんか?

「2」「*」「6」「0」各キーを入力して「sin」キーか「cos」キーを押した後、「=」押せば大体望み通りの結果が出てると思いますけど

Q変数について(足し算・引き算)

#include<stdio.h>

main () {

int i ;
int j ;

printf("第1の引数は?\n");
scanf("%d" , &i);
printf("%d\n" , i);

printf("第2の引数は?\n");
scanf("%d" , &j);
printf("%d\n" , j);


printf("和は、%d\n" , i+j);

printf("差は、%d\n" , i-j);

printf("積は、%d\n" , i*j);

printf("商は、%d\n" , i/j);

return;
}

これを実行すると(iを20 jを10)としたときに
和は、30
差は、10
積は、200
商は、2
と表示されます。

しかし、このようにプログラミングすると
足し算や、引き算の値が変になります。

#include<stdio.h>

main () {

int i ;
int j ;
int tashizann = i + j;
int hikizann = i - j;
int kakezann = i * j;
int warizann = i / j;

printf("第1の引数は?\n");
scanf("%d" , &i);
printf("%d\n" , i);

printf("第2の引数は?\n");
scanf("%d" , &j);
printf("%d\n" , j);


printf("和は、%d\n" , tashizann);

printf("差は、%d\n" , hikizann);

printf("積は、%d\n" , kakezann);

printf("商は、%d\n" , warizann);

return;
}

これを実行すると(iを20 jを10)としたときに
和は、257
差は、-255
積は、256
商は、0
と表示されます。

変数で足し算や引き算を設定したものを引数として
使うと、値がおかしくなるのかを教えて頂けませんか。

#include<stdio.h>

main () {

int i ;
int j ;

printf("第1の引数は?\n");
scanf("%d" , &i);
printf("%d\n" , i);

printf("第2の引数は?\n");
scanf("%d" , &j);
printf("%d\n" , j);


printf("和は、%d\n" , i+j);

printf("差は、%d\n" , i-j);

printf("積は、%d\n" , i*j);

printf("商は、%d\n" , i/j);

return;
}

これを実行すると(iを20 jを10)としたときに
和は、30
差は、10
積は、200
商は、2
と表示されます。

しかし、このようにプログラミングすると
...続きを読む

Aベストアンサー

>s = i + j
>↑
>変数sの中ではi、jが宣言されていない(未定義)と
>なっているのですか?確認のためにお伺いしたいと
>思っています

sの中には、計算式が入るわけではありません。
あくまでも、値が入るだけです。
また、プログラムの途中で、iやjが変化しても
自動的にsが更新されたりもしません。(Excelとは違います)
sを更新したい場合は、再度
s = i + j
を実行しないといけません。

Q三角関数計算方法

x=π/6としてみると
・(sin(x))^2
= (sin(π/6))^2
= 1/4

・sin(x^2)
= sin(π^2/36)
≒ 0.27

 上記の計算が全然分かりません。
三角関数の基本が無いので、Xの値をもっと分かりやすいもので教えてください。
計算過程を細かく記載して頂けると助かります。
宜しくお願いします。

Aベストアンサー

>x=π/6としてみると
角度のπ/6の単位はラジアンで度数法の角度では30°になります。

>・(sin(x))^2
>= (sin(π/6))^2
sin(π/6)=sin30°=1/2 なので
これを二乗して
=(1/2)^2

>= 1/4
となります。

>・sin(x^2)
>= sin(π^2/36)
これをこのまま計算するには電卓やエクセルや計算サイトなどを使わないと計算できません。
π^2/36≒3.14^2/36≒9.86/36≒0.274
これを使えば三角関数表を使って
≒sin(0.274)
を求めることができます。
またπ^2/36≒3.14^2/36≒0.274<<1なので
sin(0.274)≒0.274
>≒ 0.27
と数値計算の近似値として求めることができます。

電卓を使ってより正確に計算すれば
> sin(π^2/36)
=0.27073424331002…
となります。
上記の近似計算でも、小数以下2桁までは一致してますね。

Qパーザ 複数の型の四則演算

http://www.kmonos.net/alang/boost/classes/spirit.html
上記のサイトを参考に、実数(float)も使えるように拡張しようと思いました。
union type{
int i;
float f;
};
stack<type> stk;
これで、値をスタックに積む場合は問題なく実装できました。

しかし、これを取り出す時の処理がどうしても分かりません。
これを解決する方法・参考書籍・サイトをご存じの方、よろしくお願いします。

Aベストアンサー

それこそまさに
> struct ではなく class にして型情報を隠蔽し、setter/getter で型情報を適切に扱うようにした方が便利でしょうね。
ということで。
以下のコードを参考にどうぞ。

#include <stdio.h>
class data {
enum { type_int, type_float } type;
union {
int i;
float f;
} value;
public:
data() { type = type_int; value.i = 0;}
data(int v) { type = type_int; value.i = v;}
data(float v) { type = type_float; value.f = v;}
operator int() const { return type == type_int ? value.i : (int)value.f; }
operator float() const { return type == type_int ? (float)value.i : value.f; }
};
int main(int argc, char *argv[])
{
data v;
int i;
float f;

v = data(3);
i = v;
f = v;
printf("(int)v = %d, (float)v = %f\n", i, f);

v = data(3.5f);
i = v;
f = v;
printf("(int)v = %d, (float)v = %f\n", i, f);
}


以上は、質問の int と float を使い分けるための記述ですが、
根本的な問題として、そもそも使い分ける必要があるのでしょうか
float と int だと、float の有効数字は24bitで、
intが32bitの環境なら「intで表現できるがfloatで表現できない数」というのがありえますが、
double を使えば、精度は有効数字53bitなので、32bit int で表現できる数はそのまま double でも誤差なく表現できます。
ですから、電卓を実数対応するなら、そもそも全ての「数値」をintでなくdoubleで扱うようにするだけでOKです。unionの出番はありません。

それこそまさに
> struct ではなく class にして型情報を隠蔽し、setter/getter で型情報を適切に扱うようにした方が便利でしょうね。
ということで。
以下のコードを参考にどうぞ。

#include <stdio.h>
class data {
enum { type_int, type_float } type;
union {
int i;
float f;
} value;
public:
data() { type = type_int; value.i = 0;}
data(int v) { type = type_int; value.i = v;}
data(float v) { type = type_float; value.f = v;}
operator int() const { return type == type_int ...続きを読む

Q三角関数の計算

単純な三角関数の計算に自信がありません。
cosx*cos2x=cos^2(2x)
cos2x*cos2x=cos^2(4x)
cos2x*cos3x=cos^2(6x)
cos2x+cos2x=2cos2x
cos2x+cos5x=?
全く自信がありません。
助言お願いします。

Aベストアンサー

三角関数の計算規則はある程度覚えておくのがラクなのですが、少なくとも絶対に覚えておかねばならないものが一つあります。それは「加法定理」。
sin(α±β)=sinα*cosβ±cosα*sinβ
cos(α+β)=cosα*cosβ-sinα*sinβ
cos(α-β)=cosα*cosβ+sinα*sinβ
これだけは体で覚えておかなくては話になりません。(逆に他の公式はほとんどこれで導出できる。例外は合成公式ぐらい)

ということで、とりあえず、↑に戻って計算したらどうなるか?を考えてみてください。

http://ja.wikipedia.org/wiki/%E4%B8%89%E8%A7%92%E9%96%A2%E6%95%B0#.E4.B8.89.E8.A7.92.E9.96.A2.E6.95.B0.E3.81.AE.E5.8A.A0.E6.B3.95.E5.AE.9A.E7.90.86

QC言語の四則演算について

これからプログラミングを勉強する為、C言語の入門書を買ってきたのですが、その中で、コンピューターでは四則演算を1の補数と2の補数を用いてすべて足し算で行うと書いてありました。詳しく解説してないのでどういうことなのか良くわかりません。掛け算や割り算などを足し算でできるのでしょうか。
この辺のところに詳しい方、ぜひ、ご解説をお願いします。

Aベストアンサー

他の方と同じく、C言語の勉強として必要性が全く感じられない知識です。
C言語は、メモリやスタック等のCPUの動作をある程度意識してプログラムを組む必要がある言語ですが、だからといってそんなことまで知っている必要は全くありません。
今時、小さなCPUでも四則演算の命令はありますから、この知識が必要なのは旧式のCPUのプログラマか、CPUの設計者くらいなんじゃないでしょうか?
もう、ほとんど”トリビア”に近いです。

さて、引き算を補数と足し算で行うやり方ですが、概念がわかる程度に解説させていただきます。
この補数による引き算は10進数でもできるので、10進数で説明します。
(#2さんと同じ話をしています)

(1)2進数の世界での1の補数と2の補数は、10進数の世界での9の補数と10の補数にあたります。

(2)補数を考えるときは桁数を限定しないといけません。
ここでは桁数を4桁にします。
つまり
a.0000~9999までしか数を表現できない
b.足し算をして4桁を超えた部分は無視 ← これ大事

(3)ある数Xの9の補数は、引き算をせずとも求まります。
対応表を使います。
0123456789
↓↓↓↓↓↓↓
9876543210
例えば45の4桁の9の補数は、
45=0045→9954
になります。
(4)同じく10の補数は9の補数に1を足すと得られます。
例えば45の4桁の10の補数は、
9954+1=9955
です。

さて、9と10の補数についてわかっていただいたところで早速引き算をしてみましょう。
123-45の計算をしてみます。
1)足す数と引く数を4桁で表す。
  0123
- 0045
2)引く数の10の補数を求める
  0123
  9955
3)足し算する
  0123
+ 9955
-----------------------
 10078
4)桁を超えた部分を削る
 0078
計算終了

と、こんな具合です。
2進数でも同じ要領です。
9、10の補数が1、2の補数になっただけで、桁数の限定、はみ出た桁の無視は同じです。

ところで、上のやり方で9の補数を求めるのに表を使っていましたが、2進数で1の補数を求めるときはその必要はありません。
0/1のビットを反転するだけでできるからです。
ですから2進数の引き算では、加算とビット演算だけで実現できてしまうのです。(加算だって論理演算の固まりですけどね)

....今、この知識が必要な場面を一つ思いつきました。
整数型においての負数表現です。
詳細はここでは述べませんが、その場合でも「なぜ負の数を2の補数で表現するのか?」の理由として紹介する方が適切かも知れません。
ですから根こそぎ必要ない知識ではないですが、CPUが割り算をどう計算しているのかとは、あまり関係のない話ですね。

他の方と同じく、C言語の勉強として必要性が全く感じられない知識です。
C言語は、メモリやスタック等のCPUの動作をある程度意識してプログラムを組む必要がある言語ですが、だからといってそんなことまで知っている必要は全くありません。
今時、小さなCPUでも四則演算の命令はありますから、この知識が必要なのは旧式のCPUのプログラマか、CPUの設計者くらいなんじゃないでしょうか?
もう、ほとんど”トリビア”に近いです。

さて、引き算を補数と足し算で行うやり方ですが、概念がわかる程...続きを読む

Q三角関数と電卓の計算結果

例えば、角度45度の直角三角形でsin45°は1/√2=0.7071・・・となります。三角関数表なるものを見てもそうなってます。ですが私が使ってる関数電卓で、[45]→[sin]と押すと答えは、0.6494・・・となってしまいます。他のcos、tanでも同様な傾向で計算されます。これはどうしてなのでしょうか?電卓が壊れているのか、使い方が間違っているのでしょうか?

Aベストアンサー

角度がdegreeに設定されていないのでは?
http://www2.tokai.or.jp/yosshy/trigonometric.htm

Q四則演算のプログラム

自力で解きたかったのですが、二時間考えても、とけないので
投稿させていただきます。どこを直せばよいのでしょうか
実行するときは%プログラム名 + 5 12
と入力して実行したいです。加えて参照にしている部分の
%の扱いについても教えていただけると幸いです。
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[]){
char kigou;
double num1,num2;
kigou=atof(argv[1]);
num1=atof(argv[2]);
num2=atof(argv[3]);
if(kigou=='+'){
printf("%f+%f=%f\n",num1,num2,num1+num2);
}
else if(kigou=='-'){
printf("%f-%f=%f\n",num1,num2,num1-num2);
}
else if(kigou=='x'){
printf("%f*%f=%f\n",num1,num2,num1*num2);
}
else if(kigou=='/'){
printf("%f/%f=%f\n",num1,num2,num1/num2);
}
/* else if(kigou=='%'){
printf("%f%%f=%f\n",num1,num2,num1%num2);
}*/
else{
printf("Please input +,-,x,%%.\n");}


}

自力で解きたかったのですが、二時間考えても、とけないので
投稿させていただきます。どこを直せばよいのでしょうか
実行するときは%プログラム名 + 5 12
と入力して実行したいです。加えて参照にしている部分の
%の扱いについても教えていただけると幸いです。
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[]){
char kigou;
double num1,num2;
kigou=atof(argv[1]);
num1=atof(argv[2]);
num2=atof(argv[3]);
if(kigou=='+'){
printf("%f+%f=%f\n",num1,num2,...続きを読む

Aベストアンサー

★まず引数 argv、argc とは?
・『argv』はコマンドラインの引数を、空白文字で区切ってその文字列をポインタへの配列に
 セットします。『char *argv[]』とはその定義です。
・『argc』はコマンドラインの引数を、空白文字で区切った文字列の個数です。
・よって『sample.exe abc def 123 /s /o』というコマンドラインならば、
 argc=6
 argv[0]="sample.exe" ←プログラム名など(処理系によっては空文字列かも)
 argv[1]="abc"
 argv[2]="def"
 argv[3]="123"
 argv[4]="/s"
 argv[5]="/o"
 argv[6]=NULL ←NULLポインタがセット
・となります。

●本題
・第一引数の記号は『atof』を使わずに『kigou=argv[1][0];』とすれば良い。
・argv[1]="abc"のとき、
 argv[1][0]='a'
 argv[1][1]='b'
 argv[1][2]='c'
 argv[1][3]='\0'
・として取り出せます。

●サンプル
int main( int argc, char *argv[] )
{
 char kigou = argv[1][0]; ←ここがポイント
 double num1 = atof(argv[2]);
 double num2 = atof(argv[3]);
 
 switch ( kigou ){ ←switch 文のほうが分かりやすいよ
  case '+': printf( "%f+%f=%f\n", num1, num2, (num1 + num2) ); break;
  case '-': printf( "%f-%f=%f\n", num1, num2, (num1 - num2) ); break;
  case 'x': printf( "%f*%f=%f\n", num1, num2, (num1 * num2) ); break;
  case '/': printf( "%f/%f=%f\n", num1, num2, (num1 / num2) ); break;
  case '%': printf( "%f%%%f=%f\n", num1, num2, fmod(num1,num2) ); break; ←ここも重要
  default: printf( "Please input +,-,x,/,%%.\n" ); ←『/』を追加
 }
 return( 0 );
}

最後に:
・浮動小数点の『%』は関数『fmod』を使います。→直接『%』演算子を使えません。
・整数値の『char』、『short』、『int』、『long』型などは直接『%』演算子で剰余を
 計算できますが、浮動小数点の『float』、『double』型では関数の『fmodf』、『fmod』
 の関数を使います。→テキスト(教科書)などの算術演算を参照して下さい。
・注意。割り算と剰余の場合に『num2』が『0』だと『ゼロ除算エラー』が発生します。
・『num2』が『0』のときは計算不能というエラーを表示した方が良いです。
・以上。おわり。

参考URL:http://www.bohyoh.com/CandCPP/C/Library/fmod.html

★まず引数 argv、argc とは?
・『argv』はコマンドラインの引数を、空白文字で区切ってその文字列をポインタへの配列に
 セットします。『char *argv[]』とはその定義です。
・『argc』はコマンドラインの引数を、空白文字で区切った文字列の個数です。
・よって『sample.exe abc def 123 /s /o』というコマンドラインならば、
 argc=6
 argv[0]="sample.exe" ←プログラム名など(処理系によっては空文字列かも)
 argv[1]="abc"
 argv[2]="def"
 argv[3]="123"
 argv[4]="/s"
 argv[5]="/o"
...続きを読む


人気Q&Aランキング