![]() |
|
||||||||||
|
|||||
|
Вечер добрый)
Вот нетак давно начал исполнять свою безумную мечту детства, а именно писать физический движок. И столкнулся с проблемой крайне низкой точности вычислений.. То бишь, если я запрогил расстояние от объекта до объекта 100 пх, и нахожу его по формуле "Math.sqrt(Math.pow(x1-x2,2) + Math.pow(y1-y2,2))" то у меня получаеться где-то 99.98792193. Как с этим бороться? И еще вопрос, а в С++ или яве есть подобные проблемы? |
|
|||||
|
Регистрация: Feb 2009
Сообщений: 1,195
|
Этот вопрос много раз обсуждался. Всюду так.
|
|
|||||
|
блогер
Регистрация: Oct 2005
Адрес: Днепродзержинск - город Брежнева и других логопедов
Сообщений: 1,421
Записей в блоге: 4
|
Может, не Math.pow(х, 2), а х*х ? И чему конкретно равны координаты?
В 4-м знаке ошибка - слишком как-то. Ну там есть ещё всякая веселуха, типа большие числа с маленькими складывать/вычитать не рекомендуется. |
|
|||||
|
Регистрация: Jun 2006
Сообщений: 400
|
А где-то подробней можно прочитать про это?
|
|
|||||
|
Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
|
Цитата:
А методы Math - это без сомнений. Например Math.pow вычисляется примерно так: <function name="pow">
<![CDATA[
set(x5,1);
if (X2==0) {
set(x1,1);
}
else if (X==0 && X2 < 0) {
set(x1,"9999999999");
set(x4, 1);
while (X4 <= 128) {
set(x1, X1*X1);
set(x4, X4+1);
}
set(x5,1);
}
else {
if (X2<0) {
set(x2,-X2);
set(x5,-1);
}
if (X2==1) {
set(x1,X);
}
// handle integer powers specially
else if ( (X2 - int(X2)) == 0)
{
set(x4,2);
set(x1,X);
while (X4 <= X2) {
set(x1,X1*X);
set(x4,X4+1);
}
}
else if (X < 0)
{
// can't handle non integer powers of negative numbers
// Set result to zero
set(x1,0);
set(x5,1);
}
else {
// Build the approximation for pow(x, y)
// z = x ^ y
// z = exp(y * ln(x))
// Build the approximation for log(x)
set(x1,(X-1)/(X+1));
set(x, 0); set(x4, 1); set(x3, X1*X1);
while (X4 <= 128) {
set(x, X+X1/(2*X4-1));
set(x1, X1*X3);
set(x4, X4+1);
}
set(x, 2*X*X2);
// Build the approximation for exp(x)
// X = value of x in exp(x)
// X1 = final result
// X2 = numerator
// X3 = denominator
// X4 = iterator
set(x1,0);
set(x2,1); set(x3,1); set(x4, 1);
while (X4 <= 128) {
set(x1, X1+X2/X3);
set(x2, X2*X);
set(x3, X3*X4);
set(x4, X4+1);
}
}
}
(X5<0)?(1/X1):X1;
]]>
</function>
|
|
|||||
|
Регистрация: Jun 2006
Сообщений: 400
|
i.o., да, я столкнулся с этим недавно. При повороте клипа на угол, с точностью меньше 0.025 клип начинает поворачиваться с погрешностью. Причем погрешность - случайная величина. Если поворачивать достаточно длинный клип, скажем линию, то это очень заметно.
У меня два клипа на концах линии были. Я их поставил на сцену. А так как линия не простая, то мне нужно было ее сначала нарисовать, а потом повернуть и выставить на нужную позицию. Так вот конец линии не попадал в нужный пиксель. Не то что писксель) там большая погрешность была. Но только с углами, которые не кратны 0.025 Вот и хотел бы почитать про это подробней. |
|
|||||
|
Регистрация: Apr 2010
Адрес: Earth
Сообщений: 1,897
|
Ну это уже про displayObjectы надо искать. У Number не такая гигантская погрешность.
Лучше вообще все параметры типа x y rotation хранить в одельных переменных, типа var _x:Number, var _y:Number, var _rotation:Number, и менять их. А x y rotation displayObject'а задавать из них. Это конечно вряд ли избавит от погрешности отображения. Но зато когда вы будете крутить объект ( например _rotation += 0.001), то у вас рывков и багов с поворотами не будет. |
|
|||||
|
Регистрация: Jun 2006
Сообщений: 400
|
i.o., не. Она не накапливается. Я один раз считаю и поворачиваю на эту величину. Искал я. Даже тему тут создавал. Но то ли люди не те были на форуме в тот момент, то ли объяснил плохо... Пока что разбиваю длинные линии на более короткие. Но хотелось бы проблему понять.
|
|
|||||
|
если в качестве исходных данных брать координаты визуальных объектов, то и без накапливания погрешность изначально есть из-за округления координат
var x2:Number, y2:Number, res:Number; //собственно Number x2 = y2 = 100 * Math.SQRT1_2; trace( "x2 : " + x2 );//70.71067811865476 res = Math.sqrt(Math.pow(x2, 2) + Math.pow(y2, 2)); trace( "res : " + res );//100 //координаты спрайта var test:Sprite = new Sprite(); test.x = test.y = 100 * Math.SQRT1_2; x2 = test.x; trace( "x2 : " + x2 );//70.7 y2 = test.y; res = Math.sqrt(Math.pow(x2, 2) + Math.pow(y2, 2)); trace( "res : " + res );//99.98489885977783 |
![]() |
![]() |
Часовой пояс GMT +4, время: 08:38. |
|
|
« Предыдущая тема | Следующая тема » |
|
|