円周率計算
/**
* Copyright h6k ( http://wonderfl.net/user/h6k )
* MIT License ( http://www.opensource.org/licenses/mit-license.php )
* Downloaded from: http://wonderfl.net/c/xCpW
*/
package {
import flash.display.Sprite;
import flash.events.Event;
import flash.events.MouseEvent;
import flash.text.TextField;
import flash.text.TextFieldType;
import flash.text.TextFieldAutoSize;
import flash.utils.getTimer;
public class FlashTest extends Sprite {
private var keta:int;
private var L:int; // 配列のサイズ
private var N:Array = new Array(4); // 項数用
private var q:Array = new Array(4); // 計算用
private var r:Array;
private var pi:Array; // 結果用
private var k:uint; // カウンター用
private var T:uint; // タイマー用
private var flag:Boolean = false; // スクロール用
private var kfld:TextField = new TextField();
private var pfld:TextField = new TextField();
private var tfld:TextField = new TextField();
public function FlashTest() {
// write as3 code here..
stage.frameRate = 1000;
// 配列用意
var i:int;
for (i = 0; i < 4; i++) {
q[i] = new Array(L);
r = new Array(L);
pi = new Array(L);
}
// 桁入力用
addChild(kfld);
kfld.x = 10;
kfld.y = 10;
kfld.width = 50;
kfld.height = 20;
kfld.type = TextFieldType.INPUT;
kfld.border = true;
kfld.borderColor = 0;
kfld.text = "2037";
var fld:TextField = new TextField();
addChild(fld);
fld.x = 65;
fld.y = 10;
fld.width = 90;
fld.height = 20;
//fld.border = true;
fld.text = "桁 | 式をクリック";
fld.mouseEnabled = false;
// 結果用
addChild(pfld);
pfld.width = pfld.height = 400;
pfld.x = 10;
pfld.y = 40;
pfld.border = true;
pfld.text = "ロマンという事で(笑)\n\n※ 1949年、世界初(?)のコンピュータENIACでマチンの公式を用いて\n 2037桁を計算するのに70時間掛かったとの事。";
// 時間用
addChild(tfld);
tfld.x = 10;
tfld.y = 440;
tfld.width = 400;
tfld.height = 20;
tfld.autoSize = TextFieldAutoSize.RIGHT;
tfld.mouseEnabled = false;
// ボタン
var btn:Array = new Array(3);
var bfld:Array = new Array(3);
for (i = 0; i < 3; i++) {
bfld[i] = new TextField();
bfld[i].height = 20;
bfld[i].autoSize = TextFieldAutoSize.LEFT;
bfld[i].mouseEnabled = false;
bfld[i].border = true;
btn[i] = new Sprite();
btn[i].addChild(bfld[i]);
btn[i].x = 80 * i + 160;
btn[i].y = 10;
btn[i].buttonMode = true;
btn[i].addEventListener(MouseEvent.CLICK, onMouseClick(i));
addChild(btn[i]);
}
bfld[0].text = "マチンの公式";
bfld[1].text = "ガウスの公式";
bfld[2].text = "ストーマーの公式";
// スクロール用
var scr:Array = new Array(2);
var ubtn:Array = new Array(2);
for (i = 0; i < 2; i++) {
scr[i] = new TextField();
scr[i].width = scr[i].height = 20;
scr[i].autoSize = TextFieldAutoSize.CENTER;
scr[i].mouseEnabled = false;
scr[i].border = true;
ubtn[i] = new Sprite();
ubtn[i].addChild(scr[i]);
ubtn[i].x = 410;
ubtn[i].y = 380 * i + 40;
ubtn[i].buttonMode = true;
ubtn[i].addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown(i));
addChild(ubtn[i]);
}
scr[0].text = "▲";
scr[1].text = "▼";
stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
}
// マウスが押された
private function onMouseDown(mode:int):Function {
return function(e:MouseEvent):void {
flag = true;
stage.addEventListener(Event.ENTER_FRAME, onScroll(mode));
}
}
// マウスが離された
private function onMouseUp(e:MouseEvent):void {
flag = false;
}
// マウスが押されている間スクロール
private function onScroll(mode:int):Function {
return function(e:Event):void {
if (flag) {
if (mode == 0) {
pfld.scrollV--;
} else {
pfld.scrollV++;
}
} else {
stage.removeEventListener(Event.ENTER_FRAME, arguments.callee);
}
}
}
// 計算開始
private function onMouseClick(mode:int):Function {
return function(e:MouseEvent):void {
// 桁数取得
keta = (int)(kfld.text);
if (keta <= 0) {
pfld.text = "有効な桁数を入力して下さい。";
return;
}
// 必要な配列数
L = (int)((keta / 4) + 3);
// 初期化
for (var i:int = 0; i < L; i++) {
q[0][i] = q[1][i] = r[i] = pi[i] = 0;
switch(mode) {
case 2:
q[3][i] = 0;
case 1:
q[2][i] = 0;
}
}
// 計算
k = 1;
T = getTimer();
switch(mode) {
case 0:
// π = 16arctan(1/5) - 4arctan(1/239)
N[0] = Math.floor(keta / (2 * Math.log(5) * Math.LOG10E) + 1);
N[1] = Math.floor(keta / (2 * Math.log(239) * Math.LOG10E) + 1);
q[0][0] = 16 * 5;
q[1][0] = 4 * 239;
stage.addEventListener(Event.ENTER_FRAME, machin);
break;
case 1:
// π = 48arctan(1/18) + 32arctan(1/57) - 20arctan(1/239)
N[0] = Math.floor(keta / (2 * Math.log(18) * Math.LOG10E) + 1);
N[1] = Math.floor(keta / (2 * Math.log(57) * Math.LOG10E) + 1);
N[2] = Math.floor(keta / (2 * Math.log(239) * Math.LOG10E) + 1);
q[0][0] = 48 * 18;
q[1][0] = 32 * 57;
q[2][0] = 20 * 239;
stage.addEventListener(Event.ENTER_FRAME, gauss);
break;
case 2:
// π = 176arctan(1/57) + 28arctan(1/239) - 48arctan(1/682) + 96arctan(1/12943)
N[0] = Math.floor(keta / (2 * Math.log(57) * Math.LOG10E) + 1);
N[1] = Math.floor(keta / (2 * Math.log(239) * Math.LOG10E) + 1);
N[2] = Math.floor(keta / (2 * Math.log(682) * Math.LOG10E) + 1);
N[3] = Math.floor(keta / (2 * Math.log(12943) * Math.LOG10E) + 1);
q[0][0] = 176 * 57;
q[1][0] = 28 * 239;
q[2][0] = 48 * 682;
q[3][0] = 96 * 12943;
stage.addEventListener(Event.ENTER_FRAME, stormer);
break;
}
}
}
// 結果表示
private function result():void {
tfld.text = (String)((getTimer() - T) / 1000) + " sec";
var str:String = "π = " + pi[0] + ".";
for (var i:int = 1; i < pi.length - 1; i++) {
if (i % 14 == 0) { str += "\n"; }
var s:String = (String)(pi[i]);
switch(s.length) {
case 1:
s = "000" + s;
break;
case 2:
s = "00" + s;
break;
case 3:
s = "0" + s;
break;
}
if(i * 4 <= keta) {
str += s + " ";
} else {
str += s.substr(0, 4 - (i * 4 - keta));
}
}
pfld.text = str;
}
// ストーマーの公式
private function stormer(e:Event):void {
if(k <= N[3]) {
q[0] = division(q[0], 57 * 57);
q[1] = division(q[1], 239 * 239);
r = addition(q[0], q[1]);
q[2] = division(q[2], 682);
q[2] = division(q[2], 682);
r = subtraction(r, q[2]);
q[3] = division(q[3], 12943);
q[3] = division(q[3], 12943);
r = addition(r, q[3]);
} else if(k <= N[2]) {
q[0] = division(q[0], 57 * 57);
q[1] = division(q[1], 239 * 239);
r = addition(q[0], q[1]);
q[2] = division(q[2], 682);
q[2] = division(q[2], 682);
r = subtraction(r, q[2]);
} else if (k <= N[1]) {
q[0] = division(q[0], 57 * 57);
q[1] = division(q[1], 239 * 239);
r = addition(q[0], q[1]);
} else {
r = q[0] = division(q[0], 57 * 57);
}
r = division(r, 2 * k - 1);
if (k % 2 != 0) {
pi = addition(pi, r);
} else {
pi = subtraction(pi, r);
}
if (k++ >= N[0]) {
stage.removeEventListener(Event.ENTER_FRAME, arguments.callee);
result();
} else {
tfld.text = (String)(Math.floor(k / N[0] * 100)) + " %";
}
}
// ガウスの公式
private function gauss(e:Event):void {
if(k <= N[2]) {
q[0] = division(q[0], 18 * 18);
q[1] = division(q[1], 57 * 57);
q[2] = division(q[2], 239 * 239);
r = addition(q[0], q[1]);
r = subtraction(r, q[2]);
} else if (k <= N[1]) {
q[0] = division(q[0], 18 * 18);
q[1] = division(q[1], 57 * 57);
r = addition(q[0], q[1]);
} else {
r = q[0] = division(q[0], 18 * 18);
}
r = division(r, 2 * k - 1);
if (k % 2 != 0) {
pi = addition(pi, r);
} else {
pi = subtraction(pi, r);
}
if (k++ >= N[0]) {
stage.removeEventListener(Event.ENTER_FRAME, arguments.callee);
result();
} else {
tfld.text = (String)(Math.floor(k / N[0] * 100)) + " %";
}
}
// マチンの公式
private function machin(e:Event):void {
if (k <= N[1]) {
q[0] = division(q[0], 5 * 5);
q[1] = division(q[1], 239 * 239);
r = subtraction(q[0], q[1]);
} else {
r = q[0] = division(q[0], 5 * 5);
}
r = division(r, 2 * k - 1);
if (k % 2 != 0) {
pi = addition(pi, r);
} else {
pi = subtraction(pi, r);
}
if (k++ >= N[0]) {
stage.removeEventListener(Event.ENTER_FRAME, arguments.callee);
result();
} else {
tfld.text = (String)(Math.floor(k / N[0] * 100)) + " %";
}
}
// c = a / b;
private function division(a:Array, b:int):Array {
var c:Array = new Array(L);
var surplus:int = 0;
for (var i:int = 0; i < L; i++) {
c[i] = Math.floor((a[i] + surplus) / b); // 小数点以下切捨て
surplus = ((a[i] + surplus) % b) * 10000; // 余り
}
return c;
}
// c = a - b
private function subtraction(a:Array, b:Array):Array {
var c:Array = new Array(L);
var bollow:int = 0; // 桁下げ
for (var i:int = L - 1; i >= 0; i--) {
c[i] = a[i] - b[i] - bollow;
if (c[i] >= 0) {
bollow = 0;
} else {
c[i] += 10000;
bollow = 1;
}
}
return c;
}
// c = a + b
private function addition(a:Array, b:Array):Array {
var c:Array = new Array(L);
var carry:int = 0; // 桁上げ
for (var i:int = L - 1; i >= 0; i--) {
c[i] = a[i] + b[i] + carry;
if (c[i] < 10000) {
carry = 0;
} else {
c[i] -= 10000;
carry = 1;
}
}
return c;
}
}
}