#! /usr/bin/perl -w # Here is another way to do it, using a trigonometry 'toolkit' # approach and a different interface. Sides are \$a, \$b, and \$c, and # corresponding opposing angles are \$A, \$B, and \$C. Note that # pathological cases will break the program (e.g., using two angles # whose sum is greater than 180); more robust error checking is # required. use strict; test(); main(); sub main { print "Enter an angle (in degrees) and its opposing side:\n"; print 'Angle: '; chomp(my \$A = ); print 'Side : '; chomp(my \$a = ); print q/Enter 'a' if you have an angle, 's' if you have a side: /; GET_WHAT: chomp(my \$what = lc ); if (\$what eq 'a') { print 'Other angle: '; chomp(my \$B = ); my \$C = 180 - \$A - \$B; my \$b = aAB_to_b(\$a, \$A, \$B); my \$c = aAB_to_b(\$a, \$A, \$C); printf 'The other two sides are %.2f and %.2f, ' . "and the other angle is %.2f\n", \$b, \$c, \$C; } elsif (\$what eq 's') { print 'Other side: '; chomp(my \$b = ); my \$B = aAb_to_B(\$a, \$A, \$b); my \$C = 180 - \$A - \$B; my \$c = aAB_to_b(\$a, \$A, \$C); printf 'The other side is %.2f, ' . "and the other two angles are %.2f and %.2f\n", \$c, \$B, \$C; } else { print q/Please enter 'a' or 's': /; goto GET_WHAT; } } sub aAb_to_B { my (\$a, \$A, \$b) = @_; return rad2deg(asin(\$b * sin(deg2rad(\$A)) / \$a)); } sub aAB_to_b { my (\$a, \$A, \$B) = @_; return sin(deg2rad(\$B)) * \$a / sin(deg2rad(\$A)); } sub asin { my \$sine = shift; return undef unless \$sine >= -1 && \$sine <= 1; return atan2(\$sine, sqrt(1 - \$sine * \$sine)); } use constant PI => 4 * atan2(1, 1); sub deg2rad { \$_[0] / 180 * PI } sub rad2deg { \$_[0] / PI * 180 } sub test { # More tests would be welcome. expect('aAB_to_b', 10, 5, 30, 90); expect('aAb_to_B', 90, 5, 30, 10); } sub expect { my (\$sub, \$exp, @args) = @_; no strict 'refs'; my \$got = \$sub->(@args); return if abs(\$got - \$exp) < 0.0001; local \$" = ', '; printf "Expected \$sub(@args) to give \$exp, but got %.2f\n", \$got; }