JavaScript 数値演算 新しいページはコチラ
提供: yonewiki
(→三角関数 sin/cos/tan/asin/acos/atan/atan2) |
|||
1行: | 1行: | ||
[[JAVA Script#リファレンス]]に戻る。 | [[JAVA Script#リファレンス]]に戻る。 | ||
− | + | <yjavascript> | |
− | + | onload = function() { | |
− | + | draw1(); | |
− | + | draw2(); | |
− | + | draw3(); | |
+ | }; | ||
+ | </yjavascript> | ||
109行: | 111行: | ||
サンプル | サンプル | ||
− | < | + | <syntaxhighlight2 lang="javascript" line start="1"> |
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
130行: | 132行: | ||
</BODY> | </BODY> | ||
</HTML> | </HTML> | ||
− | </ | + | </syntaxhighlight2> |
158行: | 160行: | ||
<yjavascript> | <yjavascript> | ||
− | |||
− | |||
− | |||
− | |||
/* 円を描く */ | /* 円を描く */ | ||
function draw1() { | function draw1() { | ||
297行: | 295行: | ||
− | そのことを明示した図は以下のFLASHコンテンツ | + | そのことを明示した図は以下のFLASHコンテンツ swfアニメーションで示しました。左下隅の黒三角の再生ボタンでsin cos単心円(半径1)連動波形アニメーションが開始されます。 |
<oflash file="{{filepath:SinCosTan単位円解説2.swf}}" caption="SinCosTan単位円解説 for UploadWiki" width=700 height=120 /> | <oflash file="{{filepath:SinCosTan単位円解説2.swf}}" caption="SinCosTan単位円解説 for UploadWiki" width=700 height=120 /> | ||
単位円を上下に青い線が伸び縮みしているのがsin値で橙色の線が伸び縮みしているのが、cos値になります。本来は半径を示す斜めの線との比率が、それぞれの値なのですが、半径が1なので分母が1になるため、それぞれの青い線や橙色の線の長さそのものが、sinやcosの比率値になるわけです。tan値は示しませんでしたが、これも半径が1であるため、x=1や-1の線上と斜めの線が交わる部分の縦の長さこそがtan値になるわけです。これでお分かりいただけないのなら、わたくしめに説明するのは、もう無理です。違う勉強会に参加してみて下さい。 | 単位円を上下に青い線が伸び縮みしているのがsin値で橙色の線が伸び縮みしているのが、cos値になります。本来は半径を示す斜めの線との比率が、それぞれの値なのですが、半径が1なので分母が1になるため、それぞれの青い線や橙色の線の長さそのものが、sinやcosの比率値になるわけです。tan値は示しませんでしたが、これも半径が1であるため、x=1や-1の線上と斜めの線が交わる部分の縦の長さこそがtan値になるわけです。これでお分かりいただけないのなら、わたくしめに説明するのは、もう無理です。違う勉強会に参加してみて下さい。 | ||
+ | |||
+ | |||
+ | *sin = 正弦せいげん | ||
+ | *cos = 余弦よげん | ||
+ | *tan = 正接せいせつ | ||
+ | |||
+ | と日本語では、このように命名されています。 | ||
376行: | 381行: | ||
atan2関数は引数を二つとる関数になっています。通常はY軸となる高さをX軸となる幅で割った値をatan関数の引数として角度を算出するのが、アークタンジェントの計算になりますが、そういった算術式を引数としなくても、atan2関数は第一引数にy軸方向の値、第二引数にx軸方向の値を与えると、その長さに対応する角度の値をラジアンに相当する値として答えを返してくれる関数です。具体的な関数の利用方法についてのサンプルは後述のとおりとなります。 | atan2関数は引数を二つとる関数になっています。通常はY軸となる高さをX軸となる幅で割った値をatan関数の引数として角度を算出するのが、アークタンジェントの計算になりますが、そういった算術式を引数としなくても、atan2関数は第一引数にy軸方向の値、第二引数にx軸方向の値を与えると、その長さに対応する角度の値をラジアンに相当する値として答えを返してくれる関数です。具体的な関数の利用方法についてのサンプルは後述のとおりとなります。 | ||
+ | |||
+ | |||
+ | サンプル | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript 三角関数</TITLE> | ||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript 三角関数<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | document.write('<TABLE BORDER="1" cellspacing="0">\n'); | ||
+ | document.write('<TR>\n'); | ||
+ | document.write(' <TD>[度]</TD><TD>sin</TD><TD>cos</TD><TD>tan</TD>\n'); | ||
+ | document.write('</TR>\n'); | ||
+ | for(var i = 0;i <= 360;i++){ | ||
+ | document.write('<TR>\n'); | ||
+ | document.write(" <TD>", i, "</TD><TD>", Math.sin(i * Math.PI /180), "</TD><TD>", Math.cos(i * Math.PI /180), "</TD><TD>", Math.tan(i * Math.PI /180), "</TD>\n"); | ||
+ | document.write('</TR>\n'); | ||
+ | } | ||
+ | document.write('</TABLE>\n'); | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | [[Media:JavaScript Math TriFunc.html|サンプル実行結果]] | ||
+ | |||
+ | サンプルは三角関数表を出力するものですが、ものすごい桁数まで、コンピュータの限界に迫る計算結果になっています。tan 90度は一般には∞という解になるとされていますが、javascriptではvar i変数の最大値を返却します。また、sin360やtan360も0になるはずですが、引数に渡す値が360度のラジアン値であるため、πを使って算出していますが、Math.PIが近似値であるために、完全には0になりません。このような問題を解決するのが四捨五入や切り捨てや切り上げという考え方があります。このことについては後述の項目で、説明できる機会がありそうです。それまでは、このぐちゃぐちゃとしたみたこともない三角関数表を楽しんで頂ければと思います。ここまで計算できるという限界や誤差の発生パターンを知るのも大事だと思います。 | ||
=== 最小値・最大値 max/min === | === 最小値・最大値 max/min === | ||
+ | 例えば、3,-1,13,5,9,25,-0.51,3.9,9.9といった数字の集まりがあった場合に最大値と最小値ってのは、人間が目視ですぐに、 | ||
+ | 最大値が25で最小値は-1だと言えますが、コンピュータがそれを見つけるにはなかなか地味な作業を繰り返さなければ、最大値を正確に返答することができません。地味に最初に表示されている3が最大として、次の数字と比較してどうなのかを確認しながら最後までチェックするのです。最小値も同じことです。人間は一瞬みただけですぐに最大、最小が判別できますが、何気に高度な比較をやっていることもあります。しかし、これが数字の羅列が1万や10万という個数になった場合にもコンピュータは間違いなく、最後まで比較をやって答えを正確に導き出せるという人間技からは到底考えられない地味な働きを行うことができます。間違えないという点では、コンピュータには勝てないかもしれません。途中にでてくる-0.51という数字があるだけでも一瞬、-1との比較で間違えそうになるかもしれません。 | ||
+ | |||
+ | |||
+ | MAXはミナ、ナナ…ちがった。maxはMaximum、minはMinimumの略だと思われます。 | ||
+ | |||
+ | |||
+ | ともかく、そういった作業をするための関数がMath.maxであり、Math.minです。自分でプログラムして大きい値がどっちか、小さい値がどっちかを求めるものを作ることも可能ですが、関数としても提供されています。コーディング量が節約できるので、うまく活用するのも良いと思います。 | ||
+ | |||
+ | |||
+ | 例えば、以下のように記述することで、比較ができます。 | ||
+ | |||
+ | <ymath>*var nMaxTemp = Math.max$($3,-1$)$;</ymath> | ||
+ | *var nMinTemp = Math.min$($3,-1$)$; | ||
+ | |||
+ | という具合です。多くの数の中から最大、最小を求める場合は以下のサンプルのようにプログラムを組む必要があるでしょう。 | ||
+ | |||
+ | |||
+ | サンプル | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript max min</TITLE> | ||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript max min<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | var prevNumber = ""; | ||
+ | var arrNumber = new Array(3,-1,13,5,9,25,-0.51,3.9,9.9); | ||
+ | document.write("配列arrNumber="); | ||
+ | for(var element in arrNumber){ | ||
+ | if(arrNumber[element] != ""){ | ||
+ | if(prevNumber == ""){ | ||
+ | prevNumber = arrNumber[element]; | ||
+ | nMaxTemp = prevNumber; | ||
+ | nMinTemp = prevNumber; | ||
+ | } | ||
+ | else{ | ||
+ | prevNumber = arrNumber[element]; | ||
+ | nMaxTemp = Math.max(nMaxTemp, arrNumber[element]); | ||
+ | nMinTemp = Math.min(nMinTemp, arrNumber[element]); | ||
+ | } | ||
+ | } | ||
+ | document.write(arrNumber[element], ","); | ||
+ | } | ||
+ | document.write("<BR />\n"); | ||
+ | document.write("最大値 = ", nMaxTemp, "<BR />\n"); | ||
+ | document.write("最小値 = ", nMinTemp, "<BR />\n"); | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math MaxMin.html|サンプル実行結果]] | ||
+ | |||
+ | |||
+ | ちなみにMAXのもう一人はレイナさんですね。はい~v$($・-・$)$v♪ | ||
+ | |||
=== 絶対値 abs === | === 絶対値 abs === | ||
+ | 絶対値って?難しくないです。幅の長さ、みたいなもんです。え?幅?長さ?。そう、マイナスの概念が存在しない世界です。あそこからあそこまでの幅はいくら?って感じです。それが絶対値。どういうこと?例えば大阪を基点に東京は500km、広島は-300kmと数値が与えられたとします。で、広島までの長さは?となると絶対値の-300kmと表現します。つまりは300kmです。それだけのことです。 | ||
+ | |||
+ | |||
+ | 人間が言葉で表すのは簡単な事です。マイナスがついていたら、マイナスをとるという作業を何の気なしにやってると思います。数学的に表現すると絶対値の-300kmは以下のように記述します。 | ||
+ | |||
+ | |||
+ | 広島までの幅の長さ[km] <ymath>$= | -300 \times 10^3 |$</ymath> | ||
+ | |||
+ | |||
+ | そして、大阪を基点とした距離l$($小文字のエル$)$[km]が与えられたとして、幅の長さd$($distance$)$[km]はどう表すかというと | ||
+ | |||
+ | |||
+ | <ymath>$d \times 10^3 = | l \times 10^3 |$</ymath> | ||
+ | |||
+ | |||
+ | です。それをプログラムで表現すると | ||
+ | |||
+ | |||
+ | *Math.abs$($l * 1/$($10 * 10 * 10$)$$)$ | ||
+ | |||
+ | |||
+ | ですね。absはアンチロックブレーキシステムです。違う。absはアブソリュート:absoluteの略です。 | ||
+ | |||
+ | |||
+ | サンプル | ||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript abs</TITLE> | ||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript abs<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | var nDiff = Math.abs(1000 - 7100); | ||
+ | document.write("絶対値 |1000 - 7100| = ", nDiff, "<BR />\n"); | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math Absolution.html|サンプル実行結果]] | ||
+ | |||
=== 切り捨て・切り上げ・四捨五入 floor/ceil/round === | === 切り捨て・切り上げ・四捨五入 floor/ceil/round === | ||
+ | 切り捨て、切り上げ、四捨五入。聞いたことある言葉であってほしいです。切り捨てとは、能力のないと思われた人が、偉い人から会社を追い出されるようなことです。この例え、なんか違うな…えっと切り捨てとは、8:00発の満員電車の押し込まれて乗車しようとしたものの扉がどうしても閉まらず、取り残されるようなことです。う~ん、これも違うな。切り捨てとは、例えば、会費が4500円の飲み会があったとして、2年目以内の新人さんは1000円より少ない額については切り捨て、4000円でいいよ!と、500円を免除されるようなことです。小数点以下の値で切り捨てがされることも多いですが、大きい位でも切り捨てはされます。いらない人間はいないので人間が切り捨てられることはありません。切り捨てではなく、社会構造上の問題による組織編成の変更であり、捨てたわけではないのです。捨てた捨てられたと思う人もいるかもしれません。新しい世界が待ち受けているハズなのです。自分の能力を信じるしかありません。ポジティブに!って無理があるか…。現実はそう甘くない。切り上げは、例えば10個入りのお菓子を買う場合、42人全員に1個以上のお菓子を割り当てる必要がある場合にお菓子は50個買わなければならず、人数に応じて、ある区切りを超えたら、とにかく多く準備しなければならいようなケースです。 | ||
+ | |||
+ | |||
+ | 四捨五入は伝統的な近似表現で、ある位に注目して4以下なら切り捨て、5以上なら切り上げるという手法です。このように切り捨て・切り上げ・四捨五入には、処理を行う数値と、どこの位で切り上げや切り捨て、四捨五入をするのかを指示する必要があるのですが、用意された関数にはどの位でそれを処理するかという指示はできなくて、すべて小数点第一位を対象に実施されます。したがって、一の位を対象にしたい場合は10分の1の値にしてから切り上げ・切り捨て・四捨五入を行い、その後10倍するというやり方になります。 | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript floor,ceil,round</TITLE> | ||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScriptvz floor,ceil,round<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | function funcFCR(strMode,nValue,nPower){ | ||
+ | strMode = strMode.toLowerCase(); | ||
+ | if(nPower <= -1){ | ||
+ | fReturn = nValue * Math.pow(10,-1 * nPower - 1); | ||
+ | } | ||
+ | else{ | ||
+ | fReturn = nValue * Math.pow(10,-1 * nPower); | ||
+ | } | ||
+ | switch(strMode){ | ||
+ | case 'floor': | ||
+ | case 'f': | ||
+ | fReturn = Math.floor(fReturn); | ||
+ | break; | ||
+ | case 'ceil': | ||
+ | case 'c': | ||
+ | fReturn = Math.ceil(fReturn); | ||
+ | break; | ||
+ | case 'round': | ||
+ | case 'r': | ||
+ | fReturn = Math.round(fReturn); | ||
+ | break; | ||
+ | default: | ||
+ | return nValue; | ||
+ | } | ||
+ | if(nPower <= -1){ | ||
+ | fReturn = fReturn * Math.pow(10,nPower + 1); | ||
+ | } | ||
+ | else{ | ||
+ | fReturn = fReturn * Math.pow(10,nPower); | ||
+ | } | ||
+ | return fReturn; | ||
+ | } | ||
+ | var nValue1 = -7123; | ||
+ | var nValue2 = 6655; | ||
+ | var nValue3 = 21.4 | ||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue1, "<BR />\n"); | ||
+ | document.write(nValue1, "(十の位で切り捨て) = ", funcFCR('floor',nValue1,2), "<BR />\n"); | ||
+ | document.write(nValue1, "(一の位で切り捨て) = ", funcFCR('floor',nValue1,1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue1,0), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue1,-1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第二位で切り捨て) = ", funcFCR('floor',nValue1,-2), "<BR />\n"); | ||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue2, "<BR />\n"); | ||
+ | document.write(nValue2, "(十の位で切り捨て) = ", funcFCR('floor',nValue2,2), "<BR />\n"); | ||
+ | document.write(nValue2, "(一の位で切り捨て) = ", funcFCR('floor',nValue2,1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue2,0), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue2,-1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第二位で切り捨て) = ", funcFCR('floor',nValue2,-2), "<BR />\n"); | ||
+ | |||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue3, "<BR />\n"); | ||
+ | document.write(nValue3, "(一の位で切り捨て) = ", funcFCR('floor',nValue3,1), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue3,0), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で切り捨て) = ", funcFCR('floor',nValue3,-1), "<BR />\n"); | ||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue1, "<BR />\n"); | ||
+ | document.write(nValue1, "(十の位で切り上げ) = ", funcFCR('ceil',nValue1,2), "<BR />\n"); | ||
+ | document.write(nValue1, "(一の位で切り上げ) = ", funcFCR('ceil',nValue1,1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue1,0), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue1,-1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第二位で切り上げ) = ", funcFCR('ceil',nValue1,-2), "<BR />\n"); | ||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue2, "<BR />\n"); | ||
+ | document.write(nValue2, "(十の位で切り上げ) = ", funcFCR('ceil',nValue2,2), "<BR />\n"); | ||
+ | document.write(nValue2, "(一の位で切り上げ) = ", funcFCR('ceil',nValue2,1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue2,0), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue2,-1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第二位で切り上げ) = ", funcFCR('ceil',nValue2,-2), "<BR />\n"); | ||
+ | |||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue3, "<BR />\n"); | ||
+ | document.write(nValue3, "(一の位で切り上げ) = ", funcFCR('ceil',nValue3,1), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue3,0), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で切り上げ) = ", funcFCR('ceil',nValue3,-1), "<BR />\n"); | ||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue1, "<BR />\n"); | ||
+ | document.write(nValue1, "(十の位で四捨五入) = ", funcFCR('round',nValue1,2), "<BR />\n"); | ||
+ | document.write(nValue1, "(一の位で四捨五入) = ", funcFCR('round',nValue1,1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue1,0), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue1,-1), "<BR />\n"); | ||
+ | document.write(nValue1, "(小数点第二位で四捨五入) = ", funcFCR('round',nValue1,-2), "<BR />\n"); | ||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue2, "<BR />\n"); | ||
+ | document.write(nValue2, "(十の位で四捨五入) = ", funcFCR('round',nValue2,2), "<BR />\n"); | ||
+ | document.write(nValue2, "(一の位で四捨五入) = ", funcFCR('round',nValue2,1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue2,0), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue2,-1), "<BR />\n"); | ||
+ | document.write(nValue2, "(小数点第二位で四捨五入) = ", funcFCR('round',nValue2,-2), "<BR />\n"); | ||
+ | |||
+ | |||
+ | document.write("<BR />\n"); | ||
+ | document.write(nValue3, "<BR />\n"); | ||
+ | document.write(nValue3, "(一の位で四捨五入) = ", funcFCR('round',nValue3,1), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue3,0), "<BR />\n"); | ||
+ | document.write(nValue3, "(小数点第一位で四捨五入) = ", funcFCR('round',nValue3,-1), "<BR />\n"); | ||
+ | |||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math FloorCeilRound.html|サンプル実行結果]] | ||
+ | |||
+ | |||
+ | funcFCRという切り捨て、切り上げ、四捨五入を一括で行う関数を作りました。引数は3つ必要です。 | ||
+ | #モード指定文字列$($floor$($f$)$,ceil$($c$)$,round$($r$)$※大文字・小文字区別無し$)$ | ||
+ | #処理する数値$($数値が渡されることを前提としています。数値か?判定してエラーにする処理を追加するとなおよし!性善説プログラムになってます。) | ||
+ | #処理桁位置指定。0と-1は同じにしました。いずれも小数第一位を指定したことになります。 | ||
+ | |||
+ | |||
+ | 引数は上記のような感じです。 | ||
+ | プログラム中では、まだ説明していないビルトイン関数$($あらかじめ用意されている関数$)$を2つほど使いました。powは次の項目で説明します。toLowerCase$($$)$は、文字列変数の中身を小文字にそろえる処理をするメソッド$($オブジェクト変数にぶら下がっている関数$)$です。 | ||
+ | |||
=== 平方根・べき乗(累乗根) sqrt/pow === | === 平方根・べき乗(累乗根) sqrt/pow === | ||
+ | 平方根はスクエアルート(square root)べき乗はパワー(power)で表現されます。平方根はある数xを2分の1乗したものだと言えます。つまり、$ x^{\frac{1}{2}}\times x^{\frac{1}{2}} = x^{\frac{1}{2} + \frac{1}{2}} = x $となって、$ x^{\frac{1}{2}} $を2回掛けると$x$になりますから、まさに$ x^{\frac{1}{2}} = \sqrt{x}$といえるでしょう。そうするとsqrt関数はpow関数で置き換えることができることもわかったと思います。3乗根は$ x^{\frac{1}{3}}$のように表現できますから$n$乗根は$ x^{\frac{1}{n}}$となります。そういういみでべき乗を計算できるpowerに累乗根というタイトルを付けました。ちなみに累乗根の手計算は追い込み法という方法で3乗根ならば試しに3回掛けて、目的の値より小さいかどうかを確認していく方法を自分は使いますが、中学校の英語の時間に先生がスキッドの合間の息抜きに累乗根の計算方法というのを大学時代に編み出したと、披露してくれたのですが、複雑すぎて当時は覚えられませんでした。今もう一度教えを乞うことができるのであればもう一度おしえを乞いたいところです。累乗根を効率よく手計算で算出するという技。凄かった。自分もいろいろと考えてみたことがありますが、編み出せません。 | ||
+ | |||
+ | |||
+ | 数々の数学者が独自に編み出してきた手法を伝説に残しています。わたしはこの累乗根の手計算に意外かつ高効率な計算方法が、英語の先生が考えた以上にスゴイ手法が隠されているのではないかと思っています。でも、累乗根の近似値計算ってとんでもなく大変です。でもコンピュータはあっというまに計算してしまいます。どういうアルゴリズム(手順)が組まれているのか気になりますが、きっと地味な方法で何回も何回も計算してるんでしょう。100乗根とか…近似値を手計算しろっていわれたら、つらいっす。一昼夜はかかりそうです。 | ||
+ | |||
+ | |||
+ | べき乗の小数の計算も累乗根の計算との組み合わせによって計算されます。例えば、$7^{2.93}$を計算したいとしましょう。これは$7^{2+0.93}$と書くことができます。すると$7^{2+\frac{9}{10}+\frac{2}{100}}$と表現できます。まぁ、これをコツコツ計算するときっと解にたどり着くんでしょう。あるいは近似値に…。大変です。 | ||
+ | |||
+ | |||
+ | なんだか大変そうですが、コンピュータのはじき出す計算結果にだけ頼ってきた自分です。原理だけは知ってるから、コンピュータが計算する結果が正しいと信じよう。信じるとしよう。信じる者は救われる。 | ||
+ | |||
+ | |||
+ | ところで$2^2=4$です。で、$2^1=2$ですかね。じゃ$2^0$は? | ||
+ | |||
+ | |||
+ | 2を2回かけたら4です。だから、逆に戻っていくとして、4を2で割ったら、$2^1=2$です。もう一回2で割ったら?そうです。$2^0=1$です。では$2^{-1}$は?そうですね。もう一回2で割って$\frac{1}{2}=0.5$です。こういう関係性がべき乗の定義となっています。 | ||
+ | |||
+ | |||
+ | 一応、コンピュータが計算してくれるとは言え、基礎くらいは知っておいた方がいいかと思い、ややこしい説明をしました。スクリプトとして利用するのは簡単です。サンプルは以下のとおりです。 | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript sqrt pow</TITLE> | ||
+ | <!--[if lt IE 9]><script type="text/javascript" src="ExplorerCanvas-master/excanvas.js"></script><![endif]--> | ||
+ | <script type="text/x-mathjax-config"> | ||
+ | MathJax.Hub.Config({ | ||
+ | tex2jax: { | ||
+ | inlineMath: [['$','$'], ['\\(','\\)']], | ||
+ | processEscapes: true | ||
+ | }, | ||
+ | CommonHTML: { matchFontHeight: false }, | ||
+ | displayAlign: "left", | ||
+ | displayIndent: "2em" | ||
+ | }); | ||
+ | </script> | ||
+ | <script async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML"> | ||
+ | </script> | ||
+ | |||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript sqrt pow<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | document.write('square root 2 $\\sqrt{2} = ', Math.sqrt(2),'$<BR />\n'); | ||
+ | document.write('pow 7の3乗根 $\\sqrt[3]{7} = ', Math.pow(7,1/3),'$<BR />\n'); | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math SqrtPow.html|サンプル実行結果]] | ||
=== 対数・指数函数 log/exp === | === 対数・指数函数 log/exp === | ||
+ | ネイピア数のところで少しだけ触れましたが、対数は複雑数値同士の積を指数で近似表現することで、積の計算を和の計算に還元するもので対数表があれば、手計算で和の計算をするだけで積の近似計算ができます。指数部だけでの計算をするために使われるのがlogによる表現です。 | ||
+ | |||
+ | |||
+ | そして、その指数の底がネイピア数なのでした。そして、ネイピア数を底とした指数計算をするための関数がexp関数です。 | ||
+ | |||
+ | |||
+ | $e^{x}$のxに数値を与えて、その値を計算するためのものです。対数表を見ずとも近似値を算出できるわけです。コンピュータって便利ですね。つうか対数なんか使わなくてもコンピュータにやらせたら、なんでも計算できるじゃんと思いました?そうですよね。自分もそう思った時がありました。でも、指数表現する数値は、普段使っている数値とは天文学的に桁が違うわけです。なので、コンピュータがあるからといって、対数を使わないで計算するようなことは資源の無駄にしかなりません。 | ||
+ | |||
+ | |||
+ | それが、数学の価値なのです。人間が編み出した効率の良い数値のための仕組みなのです。多少コンピュータのリソースを無駄にするくらいで、わたしのような凡人が抱える問題は解決できることがほとんどです。だから、まぁ無理して使わなくてもいいんですけど、利用するケースは意外とあります。例えば、電力利得とか、音の大きさとかを制御する計算をするときはデシベルという単位を使います。正確にはデシはデシリットルのデシと同じく、量の単位ですので、ベルが単位になります。指数的増加を見せる現象というのは、音の振動やら電気信号やら電波(短波・長波・電磁波・光・可視光・放射線)やら宇宙における各種現象といった具合に案外、身近な自然界に存在しています。 | ||
+ | |||
+ | |||
+ | わかったようなわからないような説明ですが、ネイピア数の指数部を独立変数xとした関数を微分しても傾きがネイピア数のx乗という元の値になるという美しい値を持つネイピア数の導出に関する話を省いたり、もっと難しい話は避けてきましたので、もっともっと数学は奥が深いです。基礎の基礎だけ説明させてもらいました。自分が放送大学で勉強したような内容。数列や場合の数、ベクトル、解析幾何、微分、積分、微分方程式、素因数分解、素因数の一意性。もっと踏み込めば、級数展開、行列演算、線形代数、数学の歴史、さらにはゲーテルの不完全性定理、ガロア理論…、フェルマーの最終定理…ラングランズ・プログラム…なんでもは知らないけど、知ってることだけ。せめて微分方程式あたりに到達することで見えてくる数学の面白さのSTART地点くらいまでは導きたいと考えていますが、ソレについては別の記事で説明したいと思います。独自の解釈で間違っていたりする部分もあるかもしれないので、正確にわかりやすく説明できるかが心配ですが、自分の話をまじめに聞いてもらえれば、ちょっとくらいは実際の現場に役に立つ数学知識に変化すると自負しています。 | ||
+ | <yjavascript> | ||
+ | /* デカルト座標 */ | ||
+ | function draw3() { | ||
+ | var canvas = document.getElementById('c3'); | ||
+ | if ((! canvas) || (! canvas.getContext) ) { return false; } | ||
+ | |||
+ | var ctx = canvas.getContext('2d'); | ||
+ | |||
+ | |||
+ | ctx.strokeStyle = 'rgb(0, 0, 0)'; | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(200, 0); | ||
+ | ctx.lineTo(200, 400); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(0, 200); | ||
+ | ctx.lineTo(400, 200); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | for(var i = 20;i < 400;i += 20){ | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(i, 195); | ||
+ | ctx.lineTo(i, 205); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(195, i); | ||
+ | ctx.lineTo(205, i); | ||
+ | ctx.stroke(); | ||
+ | } | ||
+ | |||
+ | ctx.strokeStyle = 'rgb(255, 0, 0)'; | ||
+ | for(var i = -10;i < 10;i += 0.01){ | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(200 + (i * 20), 200 - (Math.exp(i-0.1) * 20)); | ||
+ | ctx.lineTo(200 + (i * 20), 200 - (Math.exp(i) * 20)); | ||
+ | ctx.stroke(); | ||
+ | } | ||
+ | ctx.strokeStyle = 'rgb(0, 0, 255)'; | ||
+ | for(var i = -10;i < 10;i += 0.01){ | ||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(200 + (i * 20), 200 - (Math.log(i-0.1) * 20)); | ||
+ | ctx.lineTo(200 + (i * 20), 200 - (Math.log(i) * 20)); | ||
+ | ctx.stroke(); | ||
+ | } | ||
+ | ctx.strokeStyle = 'rgb(0, 0, 0)'; | ||
+ | |||
+ | /* | ||
+ | ctx.beginPath(); | ||
+ | ctx.strokeText("sin x", 130 + 65, 70 - 60 * Math.sin(0) - 30); | ||
+ | |||
+ | ctx.moveTo(130, 70 - 60 * Math.sin(0)); | ||
+ | for (var i = 1; i <= 480; i += 1) { | ||
+ | ctx.lineTo(i + 130, 70 - 60 * Math.sin( Math.PI * i / 60)); | ||
+ | } | ||
+ | ctx.stroke(); | ||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.moveTo(55 + 130, 70 - 60 * Math.sin(Math.PI * 55 / 60)); | ||
+ | ctx.lineTo(130 + 63, 70 - 60 * Math.sin(0) - 32); | ||
+ | ctx.stroke(); | ||
+ | |||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.strokeStyle = 'rgb(192, 80, 77)'; | ||
+ | |||
+ | ctx.moveTo(130, 70 - 60 * Math.cos(0)); | ||
+ | ctx.strokeText("cos x", 130 + 50, 70 - 60 * Math.cos(0) + 10); | ||
+ | |||
+ | for (var i = 1; i <= 480; i += 1) { | ||
+ | ctx.lineTo(i + 130, 70 - 60 * Math.cos( Math.PI * i / 60)); | ||
+ | } | ||
+ | ctx.stroke(); | ||
+ | |||
+ | ctx.beginPath(); | ||
+ | ctx.strokeStyle = 'rgb(192, 80, 77)'; | ||
+ | ctx.moveTo(20 + 130, 70 - 60 * Math.cos(Math.PI * 20 / 60)); | ||
+ | ctx.lineTo(130 + 48, 70 - 60 * Math.cos(0) + 8 ); | ||
+ | ctx.stroke();*/ | ||
+ | |||
+ | } | ||
+ | </yjavascript> | ||
+ | |||
+ | |||
+ | <ycanvas id="c3" width="1098" height="400"></ycanvas> | ||
+ | :<span style="color:blue">'''―――''' $y = \ln x = \log_e x$</span> | ||
+ | :<span style="color:red">'''―――''' $y = \exp(x) = e^{x}$</span> | ||
+ | |||
+ | |||
+ | デカルト座標グラフで関数を図示すると上記のようになります。この2つの関数はx=の式にしたりy=の式に変形するとxとyを入れ替えただけの形をしています。こういう関係性を逆関数といいます。2つの関数にそれぞれa、bと命名するとaはbの逆関数でbはaの逆関数ということです。デカルト座標ではy=xのグラフの線(原点を通る45度斜めの線)を境に線対称になるような図になります。関数を$f(x)$の形式で説明すると、とたんになんだかややこしく感じると思いますので、あえてこの表現は今、使いません。対数の値は指数値ですからxが巨大な数値になっても対して大きな数値にはならないことが特徴です。一方でexp関数は自然対数を底とした指数の値なのでxが増加すると巨大な数値になります。増加する割合は変化しませんので極端に大きくなるというか、段々と増えるスピードが速くなるというようなイメージまでは持たなくてもいいと思います。 | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript exp log</TITLE> | ||
+ | <!--[if lt IE 9]><script type="text/javascript" src="ExplorerCanvas-master/excanvas.js"></script><![endif]--> | ||
+ | <script type="text/x-mathjax-config"> | ||
+ | MathJax.Hub.Config({ | ||
+ | tex2jax: { | ||
+ | inlineMath: [['$','$'], ['\\(','\\)']], | ||
+ | processEscapes: true | ||
+ | }, | ||
+ | CommonHTML: { matchFontHeight: false }, | ||
+ | displayAlign: "left", | ||
+ | displayIndent: "2em" | ||
+ | }); | ||
+ | </script> | ||
+ | <script async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML"> | ||
+ | </script> | ||
+ | |||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript exp log<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | document.write('Expornential $e^{1} = \\exp(1) =', Math.exp(1),'$<BR />\n'); | ||
+ | document.write('自然対数 $\\log_\\mathrm{e} \\mathrm{e} = ', Math.log(Math.E),'$<BR />\n'); | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math ExpLog.html|サンプル実行結果]] | ||
+ | |||
=== 乱数 random === | === 乱数 random === | ||
− | + | 乱数には生成方式がどうとか?確率分布がどうとか、そういった細かい議論が起こりますが、なんしか、このrandom関数を呼び出すと0~1の間の適当な値がほぼ無作為に生成されると考えていいと思います。ゲームや音楽、仕組みの中で何が起こるかわからなくするという要素を生み出すための数値生成と言えます。何が起こるかわか内から人生は面白い。運命が決まっているとしても、運命とはどうなっているのかわからないから面白い。生まれた瞬間からすべての未来が正確に予測される人生があったとしたら、それを知ったうえで生きる人生というのは面白いのでしょうか?わからないから面白い。 | |
+ | |||
+ | |||
+ | 自分の人生はどこへ向かっているのか?どこから来て、どこへ行くのか? | ||
+ | |||
+ | |||
+ | 生きるとは学ぶこと。 | ||
+ | |||
+ | |||
+ | 学ぶことは未来を変えること。 | ||
+ | |||
+ | |||
+ | 未来を変えるとは、正確な答えは無い。 | ||
+ | |||
+ | |||
+ | だけど未来の方向をある程度の範囲に収めることはできる。 | ||
+ | |||
+ | |||
+ | 自分はそのように解釈しています。ランダムとはどこへ向かうか限りなく制御できないものです。だからこそ面白さは作れる。もっとちがったことで意思決定をしている人間のランダムとはちがった面白さです。あのひと何を考えているかわからないのときの面白さは知能というものがつかさどっています。そしてソレを計算機で実現しようとする人工知能も面白い。ただし、とちらのわからないも制御できないからこそストレスが生まれることもありえます。不満。戦争。殺し合い。恨み。呪い。制御できないからこそ無数に感情が分岐される。それが平等なのか不平等なのか?わからない。多くの人間が最終的に快感を覚える程度のランダムに関する制御を行うのがプログラムする人の腕の見せ所だと思うのです。人間が不満ばかりをかかえるランダムはあまりいらない。 | ||
+ | |||
+ | |||
+ | そのさじ加減が難しいから、ゲームも売れるもの、売れないもの、いろいろと変化します。それくらいランダムは人間の社会生活を変える要素になっているのだと思います。争いが生じてゲームがきっかけで社会的な不幸が発生するのだとしたら、それは情報技術を売る側の怠慢なのではないでしょうか?わからないからこそ結末をある程度予測するということに挑戦し続ける必要はある。 | ||
+ | |||
+ | |||
+ | 長くなりましたが、そういう重要なことを決める関数です。 | ||
+ | |||
+ | |||
+ | 使い方は | ||
+ | |||
+ | |||
+ | *Math.random$($$)$ | ||
+ | |||
+ | |||
+ | とすることで、0~1の小数値が返却されます。どういった数値になるかは呼び出すまではわからないことになっています。 | ||
+ | |||
+ | |||
+ | |||
+ | 乱数で、ある確率に収束する、乱数を生成する場合。自分は10までのn進数法をよく使います。計算は長くなります。 | ||
+ | |||
+ | |||
+ | たとえば2進数のビットをすべて乱数で求める仕組みにする場合0~0.5まではビット値0それ以外はビット値1として必要な桁数分だけ繰り返して、2進数値を10進数に変換するなりして、その値によって動作を決定するというような作り方です。10進数でも同じです。値の範囲の取り方をn等分しますので、ここの偏りをつくれば出やすい数値とかが出てしまいます。n等分を均等にするとより分布が安定するかもしれないという予想においては、10進法と2進法による数値決定が一番やりやすいです。スロットなんかでは2進数のビット数くらいの確率で乱数を発生させて動作を決めているので、n進法乱数発生というのを使って、動きを真似してみたりすることを考えたことはあります。 | ||
+ | |||
+ | |||
+ | 乱数に関する数学的考察はいろいろとありますので、これ以上の複雑な話は別の記事にでも記述したいと思います。分布にはいろいろなものがありますので、一口に乱数といってもいろいろな性質をもつものがあることも頭の片隅においておくとよいと思います。なんなら、乱数 分布で検索してより詳細なことについて確認すると良いでしょう。 | ||
+ | |||
+ | |||
+ | <syntaxhighlight2 lang="javascript" line start="1"> | ||
+ | <HTML> | ||
+ | <HEAD> | ||
+ | <TITLE>JavaScript random</TITLE> | ||
+ | <!--[if lt IE 9]><script type="text/javascript" src="ExplorerCanvas-master/excanvas.js"></script><![endif]--> | ||
+ | <script type="text/x-mathjax-config"> | ||
+ | MathJax.Hub.Config({ | ||
+ | tex2jax: { | ||
+ | inlineMath: [['$','$'], ['\\(','\\)']], | ||
+ | processEscapes: true | ||
+ | }, | ||
+ | CommonHTML: { matchFontHeight: false }, | ||
+ | displayAlign: "left", | ||
+ | displayIndent: "2em" | ||
+ | }); | ||
+ | </script> | ||
+ | <script async src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_CHTML"> | ||
+ | </script> | ||
+ | |||
+ | </HEAD> | ||
+ | <BODY> | ||
+ | JavaScript random<br /> | ||
+ | <SCRIPT Language="JavaScript"> | ||
+ | <!-- | ||
+ | for(var i=0;i < 1000;i++){ | ||
+ | document.write('乱数値 random ', i, '=', Math.random(),'<BR />\n'); | ||
+ | } | ||
+ | --> | ||
+ | </SCRIPT> | ||
+ | |||
+ | </BODY> | ||
+ | </HTML> | ||
+ | </syntaxhighlight2> | ||
+ | |||
+ | [[Media:JavaScript Math Random.html|サンプル実行結果]] | ||
+ | |||