Beefy Boxes and Bandwidth Generously Provided by pair Networks
Syntactic Confectionery Delight
 
PerlMonks  

comment on

( #3333=superdoc: print w/replies, xml ) Need Help??
Hello, fellow programmers of the cloth. I need some help. The wife of a good friend of mine is taking a trigonometry class. I thought that I'd whip up a quickie perl script that would perform the Law of Sines so she could quickly check her answers. After a bit of playing, I ended up with this:
use Math::NumberCruncher; sub asin { my $sine = shift; return undef unless ( $sine >= -1 && $sine <= 1 ); return atan2( $sine, sqrt( 1-$sine * $sine ) ); } sub LawOfSines { my ( $A, $a, $B, $b, $C, $c, $format ) = @_; return undef unless ( $A && $a ) || ( $B && $b ) || ( $C && $c ); return undef unless defined $a or defined $b or defined $c; return undef unless defined $A or defined $B or defined $C; my %angles = (); my %sides = (); my @angles = undef; my ( $var, $other, $sum ) = undef; if ( $format eq "d" ) { if ( $A ) { $angles{A} = $A; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $A ) + ); } if ( $B ) { $angles{B} = $B; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $B ) + ); } if ( $C ) { $angles{C} = $C; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $C ) + ); } } else { if ( $A ) { $angles{A} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $A ) ); } if ( $B ) { $angles{B} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $B ) ); } if ( $C ) { $angles{C} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $C ) ); } } unless ( $A > 0 && $B > 0 && $C > 0 ) { if ( $A > 0 && $B > 0 ) { $var = "C" } if ( $A > 0 && $C > 0 ) { $var = "B" } if ( $B > 0 && $C > 0 ) { $var = "A" } if ( $var eq "C" ) { $sum = $angles{B} + $angles{A}; $other = 180 - $sum; $angles{$var} = $other; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $oth +er ) ); } elsif ( $var eq "B" ) { $sum = $angles{A} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $oth +er ) ); } elsif ( $var eq "A" ) { $sum = $angles{B} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( $oth +er ) ); } undef $var; } if ( $a ) { $sides{a} = $a; } if ( $b ) { $sides{b} = $b; } if ( $c ) { $sides{c} = $c; } if ( $A > 0 && $a ) { my $x = $a / sin( $A ); if ( $b && $B == 0 ) { my $sin_B = ( 1/$x ) * $b; $B = asin( $sin_B ); $angles{B} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $B ) ); } elsif ( !$b && $B > 0 ) { $b = sprintf( "%.3f", ( $x * sin( $B ) ) ); $sides{b} = $b; } unless ( $A > 0 && $B > 0 && $C > 0 ) { if ( $A > 0 && $B > 0 ) { $var = "C" } if ( $A > 0 && $C > 0 ) { $var = "B" } if ( $B > 0 && $C > 0 ) { $var = "A" } if ( $var eq "C" ) { $sum = $angles{B} + $angles{A}; $other = 180 - $sum; $angles{$var} = $other; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "B" ) { $sum = $angles{A} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "A" ) { $sum = $angles{B} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } undef $var; } if ( $c && $C == 0 ) { my $sin_C = ( 1/$x ) * $c; $C = asin( $sin_C ); $angles{C} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $C ) ); } elsif ( !$c && $C > 0 ) { $c = sprintf( "%.3f", ( $x * sin( $C ) ) ); $sides{c} = $c; } } elsif ( $B > 0 && $b ) { my $x = $b / sin( $B ); if ( $a && $A == 0 ) { my $sin_A = ( 1/$x ) * $a; $A = asin( $sin_A ); $angles{A} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $A ) ); } elsif ( !$a && $A > 0 ) { $a = sprintf( "%.3f", ( $x * sin( $A ) ) ); $sides{a} = $a; } unless ( $A > 0 && $B > 0 && $C > 0 ) { if ( $A > 0 && $B > 0 ) { $var = "C" } if ( $A > 0 && $C > 0 ) { $var = "B" } if ( $B > 0 && $C > 0 ) { $var = "A" } if ( $var eq "C" ) { $sum = $angles{B} + $angles{A}; $other = 180 - $sum; $angles{$var} = $other; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "B" ) { $sum = $angles{A} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "A" ) { $sum = $angles{B} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } undef $var; } if ( $c && $C == 0 ) { my $sin_C = ( 1/$x ) * $c; $C = asin( $sin_C ); $angles{C} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $C ) ); } elsif ( !$c && $C > 0 ) { $c = sprintf( "%.3f", ( $x * sin( $C ) ) ); $sides{c} = $c; } } elsif ( $C > 0 && $c ) { my $x = $c / sin( $C ); if ( $a && $A == 0 ) { my $sin_A = ( 1/$x ) * $a; $A = asin( $sin_A ); $angles{A} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $A ) ); } elsif ( !$a && $A > 0 ) { $a = sprintf( "%.3f", ( $x * sin( $A ) ) ); $sides{a} = $a; } unless ( $A > 0 && $B > 0 && $C > 0 ) { if ( $A > 0 && $B > 0 ) { $var = "C" } if ( $A > 0 && $C > 0 ) { $var = "B" } if ( $B > 0 && $C > 0 ) { $var = "A" } if ( $var eq "C" ) { $sum = $angles{B} + $angles{A}; $other = 180 - $sum; $angles{$var} = $other; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "B" ) { $sum = $angles{A} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "A" ) { $sum = $angles{B} + $angles{C}; print ("Sum: $sum\n"); $other = 180 - $sum; $angles{$var} = $other; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } undef $var; } if ( $b && $B == 0 ) { my $sin_B = ( 1/$x ) * $b; $B = asin( $sin_B ); $angles{B} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $B ) ); } elsif ( !$b && $B > 0 ) { $b = sprintf( "%.3f", ( $x * sin( $B ) ) ); $sides{b} = $b; } unless ( $A > 0 && $B > 0 && $C > 0 ) { if ( $A > 0 && $B > 0 ) { $var = "C" } if ( $A > 0 && $C > 0 ) { $var = "B" } if ( $B > 0 && $C > 0 ) { $var = "A" } if ( $var eq "C" ) { $sum = $angles{B} + $angles{A}; $other = 180 - $sum; $angles{$var} = $other; $C = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "B" ) { $sum = $angles{A} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $B = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } elsif ( $var eq "A" ) { $sum = $angles{B} + $angles{C}; $other = 180 - $sum; $angles{$var} = $other; $A = sprintf( "%.10f", Math::NumberCruncher::deg2rad( +$other ) ); } undef $var; } if ( $a && $A == 0 ) { my $sin_A = ( 1/$x ) * $a; $A = asin( $sin_A ); $angles{A} = sprintf( "%.10f", Math::NumberCruncher::rad2d +eg( $A ) ); } elsif ( !$a && $A > 0 ) { $a = sprintf( "%.3f", ( $x * sin( $A ) ) ); $sides{a} = $a; } } if ( $format eq "d" ) { $A = sprintf( "%.3f", Math::NumberCruncher::rad2deg( $A ) ); $B = sprintf( "%.3f", Math::NumberCruncher::rad2deg( $B ) ); $C = sprintf( "%.3f", Math::NumberCruncher::rad2deg( $C ) ); } $A = sprintf( "%.3f", $A ); $a = sprintf( "%.3f", $a ); $B = sprintf( "%.3f", $B ); $b = sprintf( "%.3f", $b ); $C = sprintf( "%.3f", $C ); $c = sprintf( "%.3f", $c ); return ( $A, $B, $C, $a, $b, $c ); } print <<END; Enter the triangle items you have available. You must enter at least three items, including at least one side and at least one angle. In ad +dition, two of the three must be an angle and its opposing side. (i.e., B and +b ). END print ("A: "); chomp($A = <STDIN>); print ("a: "); chomp($a = <STDIN>); print ("B: "); chomp($B = <STDIN>); print ("b: "); chomp($b = <STDIN>); print ("C: "); chomp($C = <STDIN>); print ("c: "); chomp($c = <STDIN>); ( $A1, $B1, $C1, $a1, $b1, $c1 ) = LawOfSines( $A, $a, $B, $b, $C, $c, + "d" ); print <<END; A: $A1 a: $a1 B: $B1 b: $b1 C: $C1 c: $c1 END
I was more interested in doing it quickly that I was in making it efficient or elegant. Now that I have the time, though, I want to clean it up. My problem is that after looking at it for as many hours as I have, I could really use someone else's input. I use Math::NumberCruncher to perform any degree/radian conversions. I'm really just doing this for fun (egad, did I just say that I'm doing the Law of Sines for fun? I need to get out more....), so there is no hurry, but if someone could take a look at my code and give me an assist in making it more efficient and/or elegant, I would appreciate it greatly.

Thanks a bunch.
___________________
Kurt

In reply to Help w/ Law of Sines script by sifukurt

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2023-12-10 11:36 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (39 votes). Check out past polls.

    Notices?