|
|
|||||
Погрешности вычисления
Вечер добрый)
Вот нетак давно начал исполнять свою безумную мечту детства, а именно писать физический движок. И столкнулся с проблемой крайне низкой точности вычислений.. То бишь, если я запрогил расстояние от объекта до объекта 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, время: 01:07. |
|
« Предыдущая тема | Следующая тема » |
|
|