指数が整数の累乗計算pow


勉強のため、累乗計算Math.pow()を作ってみた。けど、指数が整数対応版しかできなかった。

大量に計算する場合であっても、普通にMath.powを使った方がよさそう。
 
 
◆参考
ロシア乗算
http://questionbox.jp.msn.com/qa3609014.html
指数が有理数の場合
http://w3e.kanazawa-it.ac.jp/math/category/sisuu-taisuu/ruijyou/henkan-tex.cgi?size=3&target=/math/category/sisuu-taisuu/ruijyou/yuurisuu-no-sisuu.html
 
▼Wonderfl

▼ActionScript AS3(FP10)
[sourcecode language=”as3″]
/*
Math.pow()を計算するより、指数が20以下の整数なら簡易版関数の方がちょっとだけ早い

けど、結果が微妙すぎ。

これなら、大量に計算する場合であっても、普通にMath.powを使った方がよさそう。

====以下結果例====
◆Math.pow()を計算するより、指数が20以下の整数なら簡易版関数の方がちょっとだけ早い

_a100:109:Math.powで指数100以下
_a50:104:Math.powで指数50以下
_a20:98:Math.powで指数20以下
_a10:95:Math.powで指数10以下
_a5:89:Math.powで指数5以下
_b100:112:簡易関数Mas.powで指数100以下
_b50:102:簡易関数Mas.powで指数50以下
_b20:89:簡易関数Mas.powで指数20以下
_b10:80:簡易関数Mas.powで指数10以下
_b5:81:簡易関数Mas.powで指数5以下
_a99:8:対照用に0を返すだけの関数

試しに10個、Math.powとMas.powで求めた値との比較をする。
0
0
0
0
0
0
0
0
0
0

====以上結果例====

参考
ロシア乗算
http://questionbox.jp.msn.com/qa3609014.html
指数が有理数の場合
http://w3e.kanazawa-it.ac.jp/math/category/sisuu-taisuu/ruijyou/henkan-tex.cgi?size=3&target=/math/category/sisuu-taisuu/ruijyou/yuurisuu-no-sisuu.html

*/
package {
import flash.display.Sprite;
import flash.geom.Vector3D;
import flash.text.TextField;
public class Main extends Sprite {
public var ran0:Vector.<Number>=new Vector.<Number>(10000000,true);
public var ran100:Vector.<Number>=new Vector.<Number>(10000000,true);
public var ran50:Vector.<Number>=new Vector.<Number>(10000000,true);
public var ran20:Vector.<Number>=new Vector.<Number>(10000000,true);
public var ran10:Vector.<Number>=new Vector.<Number>(10000000,true);
public var ran5:Vector.<Number>=new Vector.<Number>(10000000,true);
private var len:int=1024*1024+1;
private const PI2:Number=Math.PI*2;
private var sqrtTable:Vector.<Number>=new Vector.<Number>(len,true);
public function Main():void {
var _str:String = new String();
_str+="◆Math.pow()を計算するより、指数が20以下の整数なら簡易版関数の方がちょっとだけ早い\n\n";

for (var j:int=0; j<10000000; j++) {
ran0[j]=Math.random()*100;
ran100[j]=Math.floor(Math.random()*100);
ran50[j]=Math.floor(Math.random()*50);
ran20[j]=Math.floor(Math.random()*20);
ran10[j]=Math.floor(Math.random()*10);
ran5[j]=Math.floor(Math.random()*5);
}

benchMarkj(_a99);

_str+="_a100:"+benchMarkj(_a100)+":Math.powで指数100以下\n";
_str+="_a50:"+benchMarkj(_a50)+":Math.powで指数50以下\n";
_str+="_a20:"+benchMarkj(_a20)+":Math.powで指数20以下\n";
_str+="_a10:"+benchMarkj(_a10)+":Math.powで指数10以下\n";
_str+="_a5:"+benchMarkj(_a5)+":Math.powで指数5以下\n";
_str+="_b100:"+benchMarkj(_b100)+":簡易関数Mas.powで指数100以下\n";
_str+="_b50:"+benchMarkj(_b50)+":簡易関数Mas.powで指数50以下\n";
_str+="_b20:"+benchMarkj(_b20)+":簡易関数Mas.powで指数20以下\n";
_str+="_b10:"+benchMarkj(_b10)+":簡易関数Mas.powで指数10以下\n";
_str+="_b5:"+benchMarkj(_b5)+":簡易関数Mas.powで指数5以下\n";
_str+="_a99:"+benchMarkj(_a99)+":対照用に0を返すだけの関数\n\n\n";

_str+="試しに10個、Math.powとMas.powで求めた値との比較をする。\n";

for (j=0; j<10; j++) {
var k:int=Math.random()*len;
_str += (Math.pow(ran0[j],ran20[j]) – Mas.pow(ran0[j],ran20[j]))+"\n";
}

var text_field:TextField = new TextField();
text_field.width=stage.stageWidth;
text_field.height=stage.stageHeight;
stage.addChild(text_field);
text_field.text=_str;

}

//100万回関数を実行して、かかった時間を返す
private function benchMarkj(_fn:Function):int {
var time:Number = (new Date()).getTime();
_fn(1000000);
return (new Date()).getTime() – time;
}

private function _a100(n:uint):void {
for (var i:int = 0; i < n; i++) {
Math.pow(ran0[i],ran100[i]);
}
}

private function _a50(n:uint):void {
for (var i:int = 0; i < n; i++) {
Math.pow(ran0[i],ran50[i]);
}
}
private function _a20(n:uint):void {
for (var i:int = 0; i < n; i++) {
Math.pow(ran0[i],ran20[i]);
}
}
private function _a10(n:uint):void {
for (var i:int = 0; i < n; i++) {
Math.pow(ran0[i],ran10[i]);
}
}
private function _a5(n:uint):void {
for (var i:int = 0; i < n; i++) {
Math.pow(ran0[i],ran5[i]);
}
}

private function _b100(n:uint):void {
for (var i:int = 0; i < n; i++) {
Mas.pow(ran0[i],ran100[i]);
}
}

private function _b50(n:uint):void {
for (var i:int = 0; i < n; i++) {
Mas.pow(ran0[i],ran50[i]);
}
}
private function _b10(n:uint):void {
for (var i:int = 0; i < n; i++) {
Mas.pow(ran0[i],ran10[i]);
}
}
private function _b20(n:uint):void {
for (var i:int = 0; i < n; i++) {
Mas.pow(ran0[i],ran20[i]);
}
}
private function _b5(n:uint):void {
for (var i:int = 0; i < n; i++) {
Mas.pow(ran0[i],ran10[i]);
}
}

private function _a99(n:uint):void {
for (var i:int = 0; i < n; i++) {
zero();
}
}
private function zero():Number {
return 0;
}
}
}

import flash.display.Sprite;
class Mas extends Sprite {
public static function pow(n:Number,p:int):Number {
//指数(p)が整数の場合のみ有効
var ans:Number=1;
if (p<0) {
//p*=-1;
p>>>0;
n=1/n;
}
//var ans2:Number = Math.pow(n,p%1);
for (null; p>5; p >>= 1) {
if (p&1) {
//奇数の場合のみかける
ans*=n;
}
n*=n;
}
switch (p) {
case 1:
ans *= n;
break;
case 2:
ans *= n*n;
break;
case 3:
ans *= n;
ans *= n*n;
break;
case 4:
n *= n;
ans *= n*n;
break;
case 5:
ans *= n;
n *= n;
ans *= n*n;
break;
}

//trace(ans,ans2,ans*ans2)
return ans;
}

public static function round(n:Number):Number {
n+=0.5;
return n>0?n>>0:–n>>0;
}

public static function floor(n:Number):Number {
return n>0?n>>0:–n>>0;
}

public static function ceil(n:Number):Number {
return n>0?++n>>0:n>>0;
}

public static function abs(n:Number):Number {
return n>0?n:-n;
}
}
[/sourcecode]