Форум Flasher.ru
Ближайшие курсы в Школе RealTime
Список интенсивных курсов: [см.]  
  
Специальные предложения: [см.]  
  
 
Блоги Правила Справка Пользователи Календарь Поиск рулит! Сообщения за день Все разделы прочитаны
 

Вернуться   Форум Flasher.ru > Блоги > Блог об AS3

Оценить эту запись

Быстрый Math.round для положительных чисел

Запись от Яски размещена 17.01.2009 в 01:30
Обновил(-а) Яски 18.01.2009 в 14:42

Вместо метода Math.round можно использовать следующий подход:
Код AS3:
var value:Number = 3.3;
var roundValue:uint = uint(value + 0.5);
Этот способ работает быстрее стандартного в 30 раз. Только один минус — это будет работать только для положительных чисел. Для отрицательных чисел быстрого варианта еще не придумал.
Размещено в Action Script 3
Комментарии 16 Отправить другу ссылку на эту запись
Всего комментариев 16

Комментарии

Старый 18.01.2009 14:19 iNils вне форума
iNils
 
Аватар для iNils
Во-первых, не round, а floor для положительных и ceil для отрицательных. То есть уже возможные проблемы.
Во-вторых, int ограничен до 0x7FFFFFFF, дальше опять проблемы.
Старый 18.01.2009 14:31 Яски вне форума
Яски
Неа, как раз таки round для положительных. То, что ограничен это верно подмечено. В общем можно использовать в особо требовательных участках кода.
Старый 18.01.2009 15:15 iNils вне форума
iNils
 
Аватар для iNils
Нет. Round округляет в сторону ближайшего целого
Код AS3:
var valueA:Number = 3.3;
trace (valueA + 0.1, valueA + 0.6); // 3.4, 3.9
trace (int(valueA + 0.1), int(valueA + 0.6)); // 3, 3
trace (Math.round(valueA + 0.1), Math.round(valueA + 0.6)); // 3, 4
trace (Math.ceil(valueA + 0.1), Math.ceil(valueA + 0.6)); // 4, 4
trace (Math.floor(valueA + 0.1), Math.floor(valueA + 0.6)); // 3, 3
Как видно из примера, только floor округляет вниз как int
Старый 18.01.2009 16:12 Яски вне форума
Яски
Код AS3:
var value1:Number = 3;
var value2:Number = 3.3;
var value3:Number = 3.5;
var value4:Number = 3.8;
var value5:Number = 4;
 
trace(Math.round(value1))    // 3
trace(uint(value1 + 0.5))      // 3
 
trace(Math.round(value2))    // 3
trace(uint(value2 + 0.5))      // 3
 
trace(Math.round(value3))    // 4
trace(uint(value3 + 0.5))      // 4
 
trace(Math.round(value4))    // 4
trace(uint(value4 + 0.5))      // 4
 
trace(Math.round(value5))    // 4
trace(uint(value5 + 0.5))      // 4
Так понятней?
Старый 18.01.2009 16:47 iNils вне форума
iNils
 
Аватар для iNils
- А вы знаете, что 3 равно 4?
- Быть того не может!
- Могу доказать, 3 + 1 = 4

Вы ерунду написали. Причем тут 0.5?
Старый 18.01.2009 17:09 Яски вне форума
Яски
Напишу в виде метода, тогда может поймете
Код AS3:
function round(value:Number):uint {
  return value + 0.5;
}
Значение, возвращаемое из этого метода аналогично методу Math.round для положительных чисел.
Старый 18.01.2009 17:23 iNils вне форума
iNils
 
Аватар для iNils
Ааа я понял. Я увидел int/uint, а по скольку ценность round для меня равна нулю, я даже не стал рассматривать необходимость привода к нему и смысл 0.5 для меня ускользнул.
Старый 19.01.2009 20:51 Яски вне форума
Яски
Иногда все-таки без него никак.
Старый 27.05.2009 20:44 Gladreaman вне форума
Gladreaman
 
Аватар для Gladreaman
Яски, спасиба. Но во флэш интерпретаторе оптимизация кода кажется вообще не фурычит. Бо если код асма, то
1. добавить 0.5 (достаточно долго)
2. преобразование number в uint (очень долгая процедура в тиках)
3. mov eax, [uint value] // return
4. потом вы наверняка uint преобразовываете вновь в Number

Думаю, если нет необходимости приводить к uint, то можно обойтись с помощью floor без преобразования в uint. Как Math.floor(value+0.5) для >0 (возможно, round так и устроен, только с проверкой на знаки).

т.е. не утверждаю, но мож истинный
Код AS3:
function Math.round(v:Number)
{
     if(v>0)return Math.floor(v+0.5);
     return Math.ceil(v-0.5);
}
Обновил(-а) Gladreaman 27.05.2009 в 20:54
Старый 27.05.2009 20:52 Gladreaman вне форума
Gladreaman
 
Аватар для Gladreaman
К сожалению, для FP оптимизация заключается не в минимальном количистве набранного кода. Потому что FP является интерпретатором, и как она работает, знают только создатели (если помнят). Если бы мы писали на асме, тогда бы я сразу сказал, что и где. Там можно тик каунты считать (процессорное время) согласно таблице машинных кодов.
Старый 28.05.2009 00:29 Яски вне форума
Яски
Gladreaman, ну не от балды же я это все таки написал. Я проводил тесты, сравнивал разные способы. Оптимизация для флеш заключается в минимизации вызовов методов, оптимальном использовании памяти.
Math.floor работает медленнее, чем кастинг к uint.
Math.ceil(v-0.5) не тоже самое, что Math.round(v).
И флеш не полностью интерпретируемый, исходный код компилириуется в байт код (по синтаксису похож на асм). Затем во время выполнения JIT компилирует его в машинный код. Машинный код на разных тачках будет собственно разный, но предсказать что один участок кода будет выполняться быстрее другого можно.
Старый 28.05.2009 00:31 Яски вне форума
Яски
Как и вдругих языках максимальный эффект дает оптимизация логики программы, настолько низкоуровневые оптимизации могут дать еще немного скорости.
Старый 13.10.2009 10:41 Котяра вне форума
Котяра
 
Аватар для Котяра
для отрицательных:
Код AS3:
var value:Number = -3.6;//-3.3
var roundValue:int = int(value - 0.5);
trace (roundValue);//-4//-3
ну и соответственно общий (можно наверное оптимизировать еще)
Код AS3:
var roundValue:int =value>0? uint(value + 0.5):int(value - 0.5);
или даже:
Код AS3:
var roundValue:int =int(value +(value>0?.5: -.5))
Обновил(-а) Котяра 13.10.2009 в 10:47
Старый 13.10.2009 11:34 Яски вне форума
Яски
Код AS3:
var value:Number = -3.5;
var roundValue:int = int(value - 0.5);
trace (roundValue);// -4
trace(Math.round(value)); // -3
Старый 13.10.2009 14:01 Котяра вне форума
Котяра
 
Аватар для Котяра
мэйби.. по мне Math.round - должен округлять до ближайшего целого, т.е. до -4
http://ru.wikipedia.org/wiki/%D0%9E%...BD%D0%B8%D0%B5

Цитата:
Округление к ближайшему целому (англ. round) — наиболее часто используемое округление. Число в десятичной системе округляют до N-ого знака в зависимости от N+1 знака:

* если N+1 знак < 5, то N-ый знак сохраняют, а N+1 и все последующие обнуляют;
* если N+1 знак ≥ 5, то N-ый знак увеличивают на единицу, а N+1 и все последующие обнуляют.

Например: 11,9 → 12; −0,9 → −1; −1,1 → −1; 2,5 → 3.
тогда так:
Код AS3:
int(value +(value>0?.5: -.499999999999999))// ни больше, ни меньше)
Код AS3:
var value:Number = -3.500000000000001;//=-4
var value:Number = -3.5000000000000001;//=-3
var roundValue:int =int(value +(value>0?.5: -.499999999999999))
trace (roundValue);
trace(Math.round(value));
еще один способ:
Код AS1/AS2:
trace(value.toFixed(0));
причем здесь тоже
-3.5 -> -4

Код AS3:
var value:Number = -3.500000000000001;//=-4
var d:int=1000000;
var startTime:int = getTimer();
var a:int;
var i:int;
for(i=0;i<d;i++)
{
	a=int(value +(value>0?.5: -.499999999999999));
}
trace(getTimer()-startTime);
startTime = getTimer();
 
for(i=0;i<d;i++)
{
	a=Math.round(value);
}
trace(getTimer()-startTime);
startTime = getTimer();
for(i=0;i<d;i++)
{
	a=int(value.toFixed(0));
}
trace(getTimer()-startTime);
результат:
Цитата:
225
366
3049
маловато.. если всё-же принять что -3.5 -> -4
то более быстрый вариант:
Код AS1/AS2:
a = int(value +.5-(value>>>31));
Обновил(-а) Котяра 14.10.2009 в 14:29
Старый 17.12.2010 17:13 КорДум вне форума
КорДум
 
Аватар для КорДум
Жаль, что уже не актуально. Результаты теста на сегодняшний день:
кастомный округлятор 1431
дефолтный 323
при 1кк итераций.
 

 


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


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