#!/usr/local/bin/perl # NOTES: $USAGE = ' SYNOPSIS: Nifty Programmable Scientific Calculator AUTHOR: GPL(C) Mohsin Ahmed, http://www.cs.albany.edu/~mosh USAGE: c:/> pc ... interactive mode. 1222/3; sin($pi/4); $x = $pi/$e; $x**100; p; exit; c:/> pc "231+2**20" "0xffff-99" ... batch mode NOTES: - Math Functions: +,-,/,*,**,sqrt,log,sin,cos,tan,atan2; &,|,^,complex i; - Ouput: tobin, tohex, tooct, p (prints argument or last answer in all formats). - Perl Control (while,for,if,else); Variables (string,int,floats,arrays); Use $ans[N] or $ans to refer to previous or last answers. Use the arrow keys for editing history, which due to some quirk remains intact between sessions (95/NT). ' ; $verbose=0; # TODO: Extend to bigints and bigfloats, but no libs on mswin! # # Libs not on windows. # use Math::BigFloat; # use Math::Complex; # CONSTANTS # $pi=new Math::BigFloat atan2(1,1)*4; # $e=exp(1); $pi = 3.14159264; $deg = $pi/180; %const = ( 'pi' => $pi, 'deg' => $pi/180, ); # If command line args are given, process it and exit. if( @ARGV ){ foreach $expr (@ARGV) { print "$expr = ",&p( eval $expr ),"\n"; } exit; } # Else go into interactive mode until EOF or exit. print STDERR $USAGE, 'Input:'; while(<>){ chop; $ans[++$line] = $ans = eval $_; print STDERR "\$ans[$line] = eval $_ = $ans;\n Input:"; } # Convert binary to decimal, 32 bits, etc. -1 = ffff_ffff. # NTperl5, some limits are 16 bit. # hex(ff) = 255, tohex( 255 ) = 0xff (use for input). # oct(77) = 63, tooct( 63 ) = 077 (use for input). sub tohex { sprintf( "0x%lx", @_ ); } sub tooct { sprintf( "0%lo", @_ ); } # Print arg [last ans] in many formats. sub p { # print function. @_ = int($ans) unless @_; # Use last answer as default? my($c) = @_; sprintf( "\n" . "\t= sci %lg \n" . "\t= dec %ld \n" . "\t= char '%c'%c'%c'%c'\n" . "\t= ip '%d.%d.%d.%d'\n" . "\t= hex 0x%lx \n" . "\t= octal 0%lo \n" . "\t= bin %s" , $c, $c, $c, $c>>8, $c>>16, $c>>24, $c & 0xff, $c>>8 & 0xff, $c>>16 & 0xff, $c>>24 & 0xff, $c, $c, tobin($c) ); } # Convert an integer to a string of 0 and 1. sub tobin { my( $in ) = @_; my( $bin, $rem, ) = ""; $in = int($in); while( $in > 0 ){ if( $rem = ($in & 1) ){ $bin .= '1'; }else{ $bin .= '0'; } $in = int($in>>1); } $bin =~ s/(....)/$1_/g; join( "", reverse( split(//,$bin) )); } # Works for arbitary size, but only 32 digit accuracy. # input can be a huge float number. sub floattobin { my( $in ) = @_; my( $bin ) = ""; while( int($in) > 0 ){ print "*(* bin=$bin, in=$in\n" if $verbose; $bin .= ($in % 2); $in /= 2; print "*)* bin=$bin, in=$in\n" if $verbose; } $bin =~ s/(....)/$1_/g; join( "", reverse( split(//,$bin) )); } sub bintodec { unpack("N", pack("B32", substr("0" x 32 . shift, -32))); } # EOF