|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Modus ponens
|
Монте Карло метод + странная ошибка при рассчете Пи
Вот, хотел сделать для детишек демонстацию рассчета Пи по методу Монте Карло, и тут облом Не могу понять почему ошибка, при чем постоянно площадь круга получается больше чем нужно. Код вроде простой, ничего такого заумного...
package tests { import flash.display.BitmapData; import flash.display.BitmapDataChannel; import flash.display.Graphics; import flash.display.Sprite; import flash.display.StageAlign; import flash.display.StageScaleMode; import flash.events.Event; import flash.geom.Point; import flash.text.TextField; import flash.text.TextFormat; [SWF(width="255", height="275")] public class MonteCarloIllustration extends Sprite { private static const RADIUS:uint = 0xFF; private const _monitor:TextField = new TextField(); private const _data:BitmapData = new BitmapData(RADIUS, RADIUS, false, 0); private const _noise:BitmapData = new BitmapData(RADIUS, RADIUS, false, 0); private const _zeroPoint:Point = new Point(); private var _lastCalculated:Number = 0; private var _knownMax:Number = 0; private var _knownMin:Number = Number.MAX_VALUE; public function MonteCarloIllustration() { super(); if (super.stage) this.init(); else super.addEventListener(Event.ADDED_TO_STAGE, this.init); } private function init(event:Event = null):void { super.removeEventListener(Event.ADDED_TO_STAGE, this.init); super.stage.scaleMode = StageScaleMode.NO_SCALE; super.stage.align = StageAlign.TOP_LEFT; this.prepare(); super.addEventListener(Event.ENTER_FRAME, this.enterFrameHandler); } private function enterFrameHandler(event:Event):void { var pi:Number = this.calculate(); this._monitor.text = "Pi: " + pi; this.addNoise(); this._lastCalculated = pi; } private function prepare():void { this._monitor.width = this._monitor.y = RADIUS; this._monitor.height = 20; this._monitor.defaultTextFormat = new TextFormat("_sans"); this.paint(); super.addChild(this._monitor); } private function paint():void { var canvas:Graphics = super.graphics; canvas.beginBitmapFill(this._data); canvas.drawRect(0, 0, RADIUS, RADIUS); canvas.endFill(); } private function addNoise():void { this._noise.noise(Math.random() * int.MAX_VALUE, 0, 0xFF, BitmapDataChannel.BLUE); this._data.merge(this._noise, this._data.rect, this._zeroPoint, 0, 0, 0xFF, 0); } private function calculate():Number { var pixels:Vector.<uint> = this._data.getVector(this._data.rect); var squareAvg:uint; var circleAvg:uint; var pixel:uint; var blue:uint; var result:Number; for (var total:uint = pixels.length - 1; total > 0; total--) { pixel = pixels[total]; // Blue is the channel we use to store the distribution data blue = 0xFF & pixel; if (isInCircle(total % RADIUS, total / RADIUS)) { // Let's paint those within the circle red. circleAvg += blue; // In order to visually control that the poins are indeed within // the circle, let's paint them red. pixels[total] = 0xFF0000 | blue; } squareAvg += blue; } this._data.setVector(this._data.rect, pixels); result = 4 * circleAvg / squareAvg; if (this._knownMax) { // This is a very naive way to calculate the average :) // You may want to improve here this._knownMax = Math.max(this._knownMax, result); this._knownMin = Math.min(this._knownMin, result); result = (this._knownMax + this._knownMin + this._lastCalculated) / 3; } else this._knownMax = result; return result; } private function isInCircle(xPos:uint, yPos:uint):Boolean { // Simple Pithagor theorem: the sum of powers of two of // catheti of the rectangular triangle equals to the power of two // of it's hypotenuse. Hence, if the sum of the square of // the catheti is smaller or equal to the radius, the point is within // the circle. return (xPos * xPos + yPos * yPos) <= RADIUS * RADIUS; } } }
__________________
Hell is the possibility of sanity Последний раз редактировалось wvxvw; 05.06.2011 в 18:31. |
|
|||||
Modus ponens
|
Ну фишка-то в том, что нужно было продемонстритовать, как с помощью этого метода затрачивая меньше усилий можно прощитать сложную формулу, а получилось практически наоборот Вобщем, детерминизм рулит, по-прежнему
__________________
Hell is the possibility of sanity |
|
|||||
Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
|
wvxvw, а зачем ты через целочисленные значения пытаешься вычислить Пи?
Почему не напрямую использовать Math.random() вместо шума [0..255]? Добавлено через 1 час 18 минут package { import flash.display.Sprite; import flash.events.Event; import flash.text.TextField; public class Main extends Sprite { public function Main():void { this.computePI( 1E+06, 1E+07 ); } /// private var _txtLog : TextField; /// public function computePI( radius:Number, iterations:Number=10 ) : void { var radiusPow2:Number = radius * radius; var hits:Number = 0; var i:Number = -1; while (++i < iterations) { var rndX:Number = 2.0 * radius * (0.5 - Math.random()); var rndY:Number = 2.0 * radius * (0.5 - Math.random()); if (rndX * rndX + rndY * rndY <= radiusPow2) hits += 1.0; } var rectS:Number = 4.0 * radiusPow2; var circS:Number = rectS * hits / iterations; var PI:Number = circS / radiusPow2; this.addLog("PI: " + PI); this.addLog("rectS: " + rectS); this.addLog("circS: " + circS); this.addLog("iterations: " + iterations); this.addLog("hits: " + hits); } /// public function addLog( msg:String ) : void { if (!this._txtLog) { this._txtLog = new TextField(); this._txtLog.x = 10.0; this._txtLog.y = 10.0; this._txtLog.width = 400.0; this._txtLog.height = 300.0; this.addChild( this._txtLog ); } this._txtLog.appendText( msg + "\n" ); } } } Цитата:
__________________
Загружаем картинки, минуя ошибки безопасности |
|
|||||
Modus ponens
|
Потому что эффект тот же, точности хватит ровно на столько, на сколько ее может хватить используя конкретный численный тип и радиус. А целочисленный потому что в битмапдате точнее не будет, а хотелось чтобы с картинкой. Собственно, ради картинки и делалось. Т.е. от того, что используя число с плавающей запятой мы получим на 2-3 знака после запятой больше, с точки зрения вероятно бесконечного количества знаков после запятой разница мизерная
Но за пример спасибо. Я кстати перед этим на лиспе сваял, и там можно было с 128-bit float, но, опять же
__________________
Hell is the possibility of sanity |
Часовой пояс GMT +4, время: 09:32. |
|
« Предыдущая тема | Следующая тема » |
|
|