Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 1.0/2.0 (http://www.flasher.ru/forum/forumdisplay.php?f=93)
-   -   Как random поменять на Math.random() (http://www.flasher.ru/forum/showthread.php?t=137157)

etc 08.03.2010 14:11

Цитата:

Сообщение от AzagThoth (Сообщение 891668)
А чем Вам round не нравится?

Тем, что пределы могут не совпадать с обычным random(). В частности, может достигать верхнего.

wvxvw 08.03.2010 16:26

В принципе - баг, надо искать Флазм и смотреть почему так происходит. На сколько я знаю, флеш никогда не использовал unsafe pointers, так что причина скорее всего в вом, что оно где-то число принимает за строку... кстати, надо еще MTASCом попробовать скомпилить и посмотреть, что будет.

Хмм... MTASC такой же результат выдает, значит, скорее всего бага плеера...

udaaff 08.03.2010 17:15

wvxvw, спасибо за ответ.
Хоть и не понятно в чем конкретно баг заключается, но теперь буду осторожней с такими выражениями обращаться.

wvxvw 08.03.2010 19:22

Кстати, врезультате тестов появилось следующее:
Код AS1/AS2:

/**
 * ...
 * @author wvxvw
 */

class org.wvxvw.Type
{
        private var _name:String;
        private var _value:Function;
        private static var _tpyeHash:Object = { };
 
        private function Type(value:Function)
        {
                super();
                if (!value) throw new Error("Cannot resolve type");
                var package:String;
                var nameChain:Array/*String*/;
                _global.ASSetPropFlags(_global, null, 6, true);
                for (var p:String in _global)
                {
                        if (_global[p] === value)
                        {
                                this._name = p;
                        }
                        if (!(_global[p] instanceof Object)) continue;
                        nameChain = this.findRefRecursive(_global[p], [p], value);
                        if (nameChain) break;
                }
                if (!this._name)
                {
                        if (!nameChain)
                        {
                                throw new Error("Cannot resolve type");
                        }
                        else
                        {
                                this._name = String(nameChain.pop());
                                package = nameChain.join(".");
                                this._name = package + "::" + this._name;
                        }
                }
                this._value = value;
        }
 
        public static function resolveType(value:Function):Type
        {
                for (var p:String in _tpyeHash)
                {
                        trace(_tpyeHash[p]);
                        if (Type(_tpyeHash[p]).valueOf() == Object(value))
                                return Type(_tpyeHash[p]);
                }
                var t:Type;
                t = new Type(value);
                _tpyeHash[t.toString()] = t;
                return t;
        }
 
        public function is(value:Object):Boolean
        {
                switch (this._value)
                {
                        case Boolean:
                                return typeof value == "boolean";
                        case String:
                                return typeof value == "string";
                        case Number:
                                return typeof value == "number";
                }
                return Boolean(this._value(value));
        }
 
        public function valueOf():Object { return this._value; }
 
        private function findRefRecursive(where:Object/*Object*/,
                                                                        nameChain:Array/*String*/,
                                                                        meth:Function):Array/*String*/
        {
                var o:Object;
                var nextSibling:Array/*String*/;
                for (var p:String in where)
                {
                        o = where[p];
                        if (o === meth)
                        {
                                nameChain.push(p);
                                return nameChain;
                        }
                        else if (o instanceof Object && !(o instanceof Function))
                        {
                                nextSibling = this.findRefRecursive(o, nameChain.concat([p]), meth);
                                if (nextSibling) return nextSibling;
                        }
                }
                return null;
        }
 
        public function toString():String { return this._name; }
}

Код AS1/AS2:

import org.wvxvw.Type;
 
/**
 * ...
 * @author wvxvw
 */

class org.wvxvw.ArrayList
{
        public function get type():Type { return this._type; }
 
        public function get array():Array { return this._array.concat(); }
 
        private var _type:Type;
        private var _array:Array/*T*/;
 
        public function ArrayList(type:Type)/*T*/
        {
                super();
                this._type = type;
                this._array = [];
        }
 
        public function push(param:Object/*Null<T>*/):Number
        {
                if (param === null || this._type.is(param))
                        return this._array.push(param);
                throw new Error(param + " is not a a valid type.");
                return NaN;
        }
 
        public function unshift(param:Object/*Null<T>*/):Number
        {
                if (param === null || this._type.is(param))
                        return this._array.unshift(param);
                throw new Error(param + " is not a a valid type.");
                return NaN;
        }
 
        public function pop():Object/*Null<T>*/
        {
                return this._array.pop();
        }
 
        public function shift():Object/*Null<T>*/
        {
                return this._array.shift();
        }
 
        public function splice(where:Number, items:Number,
                                        replaceWith:ArrayList/*T*/):ArrayList/*T*/
        {
                if (replaceWith && replaceWith.type !== this._type)
                        throw new Error("Type mismatch");
                var arr:ArrayList/*T*/ = new ArrayList(this._type)/*T*/;
                var clone:Array;
                var cloneHead:Array = this._array.slice(0, where);
                var cloneTail:Array = this._array.slice(where + items, this._array.length);
                var insert:Array
                if (replaceWith)
                {
                        insert = replaceWith.array;
                        clone = cloneHead.concat(insert.concat(cloneTail));
                }
                else clone = cloneHead.concat(cloneTail);
                ArrayList/*T*/.setSource(arr, clone);
                return arr;
        }
 
        public function slice(from:Number, to:Number):ArrayList/*T*/
        {
                var arr:Array = this._array.splice(from, to);
                var arrList:ArrayList = new ArrayList(this._type)/*T*/;
                ArrayList/*T*/.setSource(arrList, arr);
                return arrList;
        }
 
        public function toString():String
        {
                return "ArrayList<" + this._type + ">[" + this._array.join(", ") + "]";
        }
 
        private static function setSource(to:ArrayList/*T*/, source:Array/*T*/):Void
        {
                to._array = source;
        }
}

Нечем было заняться :)

Самое интересное то, что если вычитать а не складывать, то результат опять же будет неправильным... и если последовательно трейсить trace(a) в первом цикле, то видно, что иногда массив не изменяется... вобщем, скорее всего какай-нибудь пропущенная команда в сгенерированом коде, либо плеер неправильно читает команду (забывает при каких-то обстоятельствах)...

etc 08.03.2010 23:03

Цитата:

Сообщение от wvxvw (Сообщение 891740)
Код AS1/AS2:

private static var _tpyeHash:Object = { };


Жертва опечатки.

wvxvw 09.03.2010 03:41

Онa все равно приватная :p

На самом деле самое глупое в этом - это ошибки кидать / ловить в AS2. В большинстве случаев плеер их сам отрабатывает и не дает до них добраться... :( т.е. если функция вернулась с ошибкой а ее вызвала другая функция, то в третей функции, которая вызвала вторую про ошибку уже все забыли, просто где-то undefined будет... Страшно подумать, что на этом когда-то что-то всерьез писалось...

Хех, еще обиднее - оказалось, что кастовать по ссылке нельзя - очевидно компилятор не умел этого делать, просто раньше я даже не задумывался о необходимости такой штуки :)

Psycho Tiger 09.03.2010 12:05

Код AS3:

for (var i:Number = 0; i < 100; i++)
{
        var k:Number = Math.round(Math.random() * 4);
        b[k]++;
        a[Math.round(Math.random() * 4)]++;
}

Я не понимаю, почему k обязанно за 100 итераций выпасти 20 раз? Ровно как и Math.round(Math.random() * 4).

udaaff 09.03.2010 12:10

Цитата:

Я не понимаю, почему k обязанно за 100 итераций выпасти 20 раз? Ровно как и Math.round(Math.random() * 4).
В смысле?
k выпадает каждую итерацию. И в сумме должно получиться 100 по идее.

wvxvw 09.03.2010 12:56

Код:

movie 'loop.swf' // flash 9, total frames: 1, frame rate: 12 fps, 550x400 px


  frame 0
    constants 'a', 'b', 'i', 'k', 'Math', 'random', 'round', 'sumA', 'sumB', 'sumA ', ' sumB ' 
    push 'a', 0.0, 0.0, 0.0, 0.0, 0.0, 5
    initArray
    varEquals
    push 'b', 0.0, 0.0, 0.0, 0.0, 0.0, 5
    initArray
    varEquals
    push 'i', 0.0
    varEquals
  label1:
    push 'i'
    getVariable
    push 100
    lessThan
    not
    branchIfTrue label2
    push 'k', 0.0, 'Math'
    getVariable
    push 'random'
    callMethod
    push 4
    multiply
    push 1, 'Math'
    getVariable
    push 'round'
    callMethod
    varEquals
    push 'b'
    getVariable
    push 'k'
    getVariable
    push 'b'
    getVariable
    push 'k'
    getVariable
    getMember
    increment
    setMember

    push 'a'
    getVariable
    push 0.0, 'Math'
    getVariable
    push 'random'
    callMethod
    push 4
    multiply
    push 1, 'Math'
    getVariable
    push 'round'
    callMethod
    push 'a'
    getVariable
    push 0.0, 'Math'
    getVariable
    push 'random'
    callMethod
    push 4
    multiply
    push 1, 'Math'
    getVariable
    push 'round'
    callMethod
    getMember
    increment
    setMember

    push 'i', 'i'
    getVariable
    increment
    setVariable
    branch label1
  label2:
    push 'sumA', 0.0
    varEquals
    push 'sumB', 0.0
    varEquals
    push 'i', 0.0
    setVariable
  label3:
    push 'i'
    getVariable
    push 5
    lessThan
    not
    branchIfTrue label4
    push 'sumA', 'sumA'
    getVariable
    push 'a'
    getVariable
    push 'i'
    getVariable
    getMember
    add
    setVariable
    push 'sumB', 'sumB'
    getVariable
    push 'b'
    getVariable
    push 'i'
    getVariable
    getMember
    add
    setVariable
    push 'i', 'i'
    getVariable
    increment
    setVariable
    branch label3
  label4:
    push 'sumA ', 'sumA'
    getVariable
    add
    push ' sumB '
    add
    push 'sumB'
    getVariable
    add
    trace
  end // of frame 0
end

Это вот что получается после компиляции - ну, давайте попробуем разобраться :)

Не знаю, я не вижу почему бы второй вариант должен так странно себя вести, скорее всего - баг плеера а не компилятора. (Хотя первый вариант все равно оптимальнее).

iNils 09.03.2010 13:34

Собственно все и так ясно.
Выражение
Код AS1/AS2:

а[Math.round(Math.random() * 4)]++

это тоже самое, что и
Код AS1/AS2:

а[Math.round(Math.random() * 4)] = а[Math.round(Math.random() * 4)] + 1

Из этого видно, что индексы в правой и левой части будет в основном отличаться (вызов будет два раза), что и приводит к тому, что сумма не равна 100.
С b все ясно, так как "k" в выражении
Код AS1/AS2:

b[k] = b[k] + 1

будет совпадать для обоих частей

В avm2 переписали инкремент, поэтому левая часть для a берется из правой части.


Часовой пояс GMT +4, время: 11:58.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.