2015-02-08 2 views
-1

Я работаю над классом векторов C#, чтобы практиковать свои навыки и учить себя, и я столкнулся с довольно безымянной проблемой.Ошибка с плавающей запятой с матрицей поворота

public void Rotate (double rotation) 
    { 
     double xT; 
     xT = x * Math.Cos (rotation * (Math.PI/180)) - y * Math.Sin (rotation * (Math.PI/180)); 
     y = x * Math.Sin (rotation * (Math.PI/180)) + y * Math.Cos (rotation * (Math.PI/180)); 
     x = xT; /*Figure out a better way to this*/ 
    } 

Этот код неаккуратно я знаю, но вопрос приходит от того, когда я пытаюсь простое вращение (1,0) на 180 градусов вокруг, вместо ожидаемого (-1,0), что я должен получить, он вместо этого возвращает (-1, -6.2343e-12) или что-то в этом роде.

Я понимаю, что это проблема с отсутствием точности в двухместных номерах, но я хочу знать, есть ли способ вернуть ей значение 0 вместо числа до -12-го.

Есть ли способ сделать это?

+1

'-0.0000000000062343' выглядит примерно как 0 для меня. Почему это вас беспокоит? Неужели это испортит ваши расчеты? Вы могли бы округлить его, но я бы не стал беспокоиться. –

+0

Это известная «проблема» в .NET с Sin/Cos. См. Самый высокий голосовой ответ в http://stackoverflow.com/questions/3249710/accuracy-of-math-sin-and-math-cos-in-c-sharp. Все, что я могу сказать, так это то, как работают двойные значения, и если вам нужны точные нули, вам нужно округлить все ваши значения до 11 десятичных точек. Эта проблема особенно плоха для значений, которые должны быть равны нулю, так как самые близкие двойные значения к нулю равны +/- 5e-324. – NextInLine

+0

Я знаю, что нет реального способа избежать этого. Просто мне очень сложно узнать что-то другое, кроме того, что я знаю, это простой и правильный ответ, я надеялся, что есть способ исправить это. – toa697

ответ

1

Это, как правило, быстрее/очиститель для работы с неизменяемыми структурами векторов

public struct Vector 
{ 
    readonly double x, y; 
    public Vector(double x, double y) { this.x=x; this.y=y; } 
    public Vector Rotate(double angle) 
    { 
     angle *= Math.PI/180; 
     double cos = Math.Cos(angle), sin=Math.Sin(angle); 
     return new Vector(
      x*cos-y*sin, 
      x*sin+y*cos); 
    } 
} 

Теперь, насколько точность идет, нет никакой альтернативы, кроме как использовать тригонометрические функции в System.Math. Я рекомендую дезинфицировать угловые вводы путем обертывания их между -180..180 перед преобразованием в радианы и использованием в функции триггера.

+0

Имеет ли этот адрес _ ", но я хочу знать, есть ли способ вернуть ему 0 вместо числа на -12th" _ – MickyD

+0

Он делает это. Я говорю «нет», если не задействована упаковка, а затем она собирается вернуть «1е-17» – ja72

+0

Гудо. Мне нравится использование неизменяемых структур – MickyD