Angle difference between two bearings: Difference between revisions
Content added Content deleted
m (used whitespace to line up definitions.) |
m (Include Erlang solution) |
||
Line 657: | Line 657: | ||
-161.503 |
-161.503 |
||
37.2989</pre> |
37.2989</pre> |
||
=={{header|Erlang}}== |
|||
The real number calculations are done using integer arithmetic to better handle |
|||
rounding errors. Erlang uses extended precision integers so there will be no overflow. |
|||
The module is tested by running the test function, which in turn matches expected results |
|||
with the result of function call. |
|||
<lang Erlang> |
|||
-module(bearings). |
|||
%% API |
|||
-export([angle_sub_degrees/2,test/0]). |
|||
-define(RealAngleMultiplier,16#10000000000). |
|||
-define(DegreesPerTurn,360). |
|||
-define(Precision,9). |
|||
%%%=================================================================== |
|||
%%% API |
|||
%%%=================================================================== |
|||
%%-------------------------------------------------------------------- |
|||
%% @doc |
|||
%% @spec |
|||
%% @end |
|||
%%-------------------------------------------------------------------- |
|||
%% |
|||
angle_sub_degrees(B1,B2) when is_integer(B1), is_integer(B2) -> |
|||
angle_sub(B2-B1,?DegreesPerTurn); |
|||
angle_sub_degrees(B1,B2) -> |
|||
NewB1 = trunc(B1*?RealAngleMultiplier), |
|||
NewB2 = trunc(B2*?RealAngleMultiplier), |
|||
round(angle_sub(NewB2 - NewB1, |
|||
?DegreesPerTurn*?RealAngleMultiplier) |
|||
/?RealAngleMultiplier,?Precision). |
|||
%%%=================================================================== |
|||
%%% Internal functions |
|||
%%%=================================================================== |
|||
%% delta normalises the angle difference. Consider a turn from 350 degrees |
|||
%% to 20 degrees. Subtraction results in 330 degress. This is equivalent of |
|||
%% a turn in the other direction of 30 degrees, thus 330 degrees is equal |
|||
%% to -30 degrees. |
|||
angle_sub(Value,TurnSize) -> |
|||
NormalisedValue = Value rem TurnSize, |
|||
minimise_angle(NormalisedValue,TurnSize). |
|||
% X rem Turn result in 0..Turn for X > 0 and -Turn..0 for X < 0 |
|||
% specification requires -Turn/2 < X < Turn/2. This is achieved |
|||
% by adding or removing a turn as required. |
|||
% bsr 1 divides an integer by 2 |
|||
minimise_angle(Angle,Turn) when Angle + (Turn bsr 1) < 0 -> |
|||
Angle+Turn; |
|||
minimise_angle(Angle,Turn) when Angle - (Turn bsr 1) > 0 -> |
|||
Angle-Turn; |
|||
minimise_angle(Angle,_) -> |
|||
Angle. |
|||
round(Number,Precision) -> |
|||
P = math:pow(10,Precision), |
|||
round(Number*P)/P. |
|||
test() -> |
|||
25 = angle_sub_degrees(20,45), |
|||
90 = angle_sub_degrees(-45,45), |
|||
175 = angle_sub_degrees(-85,90), |
|||
-175 = angle_sub_degrees(-95,90), |
|||
170 = angle_sub_degrees(-45,125), |
|||
-170 = angle_sub_degrees(-45,145), |
|||
-118.1184 = angle_sub_degrees( 29.4803,-88.6381), |
|||
-139.583283124=angle_sub_degrees(-70099.742338109,29840.674378767), |
|||
-72.343918514=angle_sub_degrees( -165313.66662974,33693.989451746), |
|||
-161.50295231=angle_sub_degrees( 1174.8380510598,-154146.66490125), |
|||
37.298855589=angle_sub_degrees( 60175.773067955,42213.071923544), |
|||
passed. |
|||
</lang> |
|||
=={{header|F#|F sharp}}== |
=={{header|F#|F sharp}}== |