MyTetra Share
Делитесь знаниями!
Нормировка угла на диапазон 0-360 и -180/+180 на языке C/C++
Время создания: 21.02.2018 13:26
Текстовые метки: язык Си, c++, угол, нормировка, нормализация, диапазон
Раздел: Компьютер - Программирование - Алгоритмы
Запись: xintrea/mytetra_syncro/master/base/15192088058hw46jy9cz/text.html на raw.github.com

Пример кода, который нормализует (ограничивает) угол в указанном диапазоне. Если значение выходит за диапазон, угол пересчитывается так, чтобы "визуально" он остался прежним, но его значение укладывалось бы в заданный диапазон.


#include <iostream>

#include <cmath>


using namespace std;


// Диапазон (0, 360)

double constrainAngle360(double x)

{

x = fmod(x ,360.0);

if (x < 0.0)

x += 360.0;

return x;

}


// Диапазон (-180, +180)

double constrainAngle180(double x)

{

x = fmod(x + 180.0, 360.0);

if (x < 0.0)

x += 360.0;

return x - 180.0;

}


int main()

{

cout << "Constrain 360:" << "\n";

cout << 0.5 << " : " << constrainAngle360(0.5) << "\n";

cout << 10 << " : " << constrainAngle360(10) << "\n";

cout << 380 << " : " << constrainAngle360(380) << "\n";

cout << 730 << " : " << constrainAngle360(730) << "\n";

cout << 730.5 << " : " << constrainAngle360(730.5) << "\n";


cout << -0.5 << " : " << constrainAngle360(-0.5) << "\n";

cout << -10 << " : " << constrainAngle360(-10) << "\n";

cout << -380 << " : " << constrainAngle360(-380) << "\n";

cout << -730 << " : " << constrainAngle360(-730) << "\n";

cout << -730.5 << " : " << constrainAngle360(-730.5) << "\n";



cout << "Constrain 180:" << "\n";

cout << 0.5 << " : " << constrainAngle180(0.5) << "\n";

cout << 10 << " : " << constrainAngle180(10) << "\n";

cout << 380 << " : " << constrainAngle180(380) << "\n";

cout << 730 << " : " << constrainAngle180(730) << "\n";

cout << 730.5 << " : " << constrainAngle180(730.5) << "\n";


cout << -0.5 << " : " << constrainAngle180(-0.5) << "\n";

cout << -10 << " : " << constrainAngle180(-10) << "\n";

cout << -380 << " : " << constrainAngle180(-380) << "\n";

cout << -730 << " : " << constrainAngle180(-730) << "\n";

cout << -730.5 << " : " << constrainAngle180(-730.5) << "\n";

return 0;

}


Результат:


Constrain 360:

0.5 : 0.5

10 : 10

380 : 20

730 : 10

730.5 : 10.5

-0.5 : 359.5

-10 : 350

-380 : 340

-730 : 350

-730.5 : 349.5

Constrain 180:

0.5 : 0.5

10 : 10

380 : 20

730 : 10

730.5 : 10.5

-0.5 : -0.5

-10 : -10

-380 : -20

-730 : -10

-730.5 : -10.5



Однако при использовании языка C99 следует учитывать вот что:


Вычисление остатка от деления в JavaScript


Цитата: если хотите снова запутаться, то попробуйте отрицательные числа (% операция является взятием остатка в Питоне (0<=(a%b)<b), но не в Си(99), где (a % b) может быть отрицательным:


-1 % 7 == 6 // в Питоне


и


-1 % 7 == -1 // в Си(99).


Деление с остатком определяется формулой:


a = b * (a / b) + (a % b)


плюс условие:


0<=(a%b)<b


— это достаточно, чтобы уникально получить a/b и a%b. В Си(99) -a/b == -(a/b) (симметрия, нарушает свойство остатка), в Питоне (a+k*b)//b == (a//b)+ k (периодичность, ведёт к "настоящему" "делению по модулю" stackoverflow.com/a/1907889/4279


А чтобы получить остаток и в Си, можно (b + (a % b)) % b формулу использовать. См. Деление с остатком, Euclidean division


Другими словами, значение a%b следует из свойств a/b. До C99 a/b зависело от реализации. C99 к нулю округляет потому что Fortran так делал, который вероятно в свою очередь использовал то что на CPU быстрее (про Фортран—со слов человека, который черновик стандарта правил<-здесь ещё более robust формулы, для остатка в Си) stackoverflow.com/q/3602827/4279

Так же в этом разделе:
 
MyTetra Share v.0.59
Яндекс индекс цитирования