A simple math pad in Perl
I finally upgraded to Lion at the office; that means no more Mark Widholm MathPad. I mostly use it just to do freeform calculations in a series, kind of a very cheap spreadsheet. It occurred to me that I ought to be able to get something close to that using the “bc” command line app that comes with Mac OS X. Combine with SilverService and it’s not as dynamic as MathPad but it’s pretty close.
[toggle code]
- #!/usr/bin/perl
- #NOTE: BC does not handle upper-case in variable names
- use warnings;
- use strict;
- use IPC::Open3;
- my($bc) = open3(\*WRITE, \*READ, 0, '/usr/bin/bc');
- print WRITE "scale=4\n";
- my($ender) = 'ENDXXQQQEND';
- my($lastResult) = '';
- my($printCommand, $tail);
- #handle both Unix and Mac line endings
- my($lines) = '';
-
while(<>) {
- $lines .= $_;
- }
- my(@lines) = split(/[\n\r\l]/, $lines);
- #handle the math a line at a time
-
for (@lines) {
- #handle mathpad comments
-
if (/^--/ || /^$/) {
- print;
-
} else {
- chomp;
- my($command);
- $_ =~ /^(.+?)(: ?[0-9.-]+)?([ \t]*--.*)?$/;
- $command = $1;
- $tail = $3;
- $printCommand = $command;
-
if ($lastResult ne '' && $command =~ /#/) {
- $command =~ s/\#/$lastResult/g;
- }
- print WRITE $command;
- print WRITE "\n";
- print WRITE "print \"$ender\\n\"\n";
- my($result, $printed);
- #a bit of a hack to ensure that there is always something to read
- #when it detects the last thing to read, it leaves
-
while($result = <READ>) {
- chomp($result);
- last if $result eq $ender;
-
if ($result ne '') {
- print "$printCommand: $result";
-
if ($tail) {
- print $tail;
- }
- $lastResult = $result;
- $printed = 1;
- }
- }
-
if (!$printed) {
- print;
- }
- }
- print "\n";
- }
I saved it as “padmath” and then set it up in SilverService. It worked great; the two problems are:
- bc sometimes returns a line and sometimes doesn’t. Perl’s pipe input reads a line at a time, so if nothing happens, the read sits there waiting for something to happen that never does. There’s probably a better way to fix it, but what I do is just echo an unlikely string after every command. Then, I put the read into a while loop and exit if I see that string.
- bc can’t handle uppercase in variable names, so any existing mathpad files using camelCase need to be modified.
Obviously this won’t do graphs or any of the other stuff that MathPad did, but it will handle by far most of what I use MathPad for.
Examples
Here’s a MathPad file I used for quick calculation of download speeds:
- --kilobytes per second
- 15
- --kilobytes per minute
- #*60
- --kilobytes per hour
- #*60
- --megabytes per hour
- #/1024
- --megabytes per day
- #*24
- --megabytes per month
- #*30
- --gigabytes per month
- #/1024
Here’s what it looks like after selecting it and running padmath on it:
- --kilobytes per second
- 15: 15
- --kilobytes per minute
- #*60: 900
- --kilobytes per hour
- #*60: 54000
- --megabytes per hour
- #/1024: 52.7343
- --megabytes per day
- #*24: 1265.6232
- --megabytes per month
- #*30: 37968.6960
- --gigabytes per month
- #/1024: 37.0788
Change the 15 to something else, and it will recalculate; just like MathPad, it ignores the parts of the lines after the colons.
Here’s another simple one, I don’t even remember what it was for, possibly something to do with time:
- remaining = 566
- used = 90
- total = remaining + used
- total/60: 10.9333
- February 28, 2013: MathPad is back!
-
Just an FYI, MathPad is back! Version 3.0.4 supports Mac OS X 10.6 and up, and works on Intel Macs without Rosetta. You’ll want to read the What’s New file; for example, I’ve been using .mathpad as the extension to get Leopard/Snow Leopard to associate my MathPad files with MathPad. In 3.0.4, the extension is officially .mp.
Another major change is that the default file format is RTF instead of text. You can save as text but there is unfortunately no preferences setting to prefer text over RTF. MathPad continues to read text files fine.
Some neat changes (I think) include the ability to use π instead of ‘pi’ in calculations.There are several other changes as well, likely related to the switch from Carbon to Cocoa.
- August 23, 2012: Adding functions to padmath
-
The simple padmath replacement for MathPad works for almost everything I used MathPad for. Every once in a while, however, I need a function that bc doesn’t have but that MathPad did. Three of the most common things I end up needing are π for determining area, and abs and trunc for getting the absolute value or to drop the fractions from a value.
The bc program does support creating functions, so I’ve added those three items to the prepended text that, previously, just set the system to use four decimal points.
Replace “print WRITE "scale=4\n";” with:
[toggle code]
- #functions
- print WRITE <<'ENDFUNCTIONS';
- #padmath values
- pi = 3.1416
- #padmath functions
-
define abs(value) {
-
if (value < 0) {
- return -value
-
} else {
- return value
- }
-
if (value < 0) {
- }
-
define trunc(value) {
- old_scale=scale
- scale=0
- int_value=value/1
- scale=old_scale
- return int_value
- }
- #not in MathPad
-
define ceiling(value) {
- return -floor(-value);
- }
-
define floor(value) {
- int_value = trunc(value)
-
if (value != int_value && value < 0) {
- int_value = int_value -1
- }
- return int_value
- }
- scale=4
- ENDFUNCTIONS
So I can now do something like this because I’m looking for a year:
- --25-year shingles reduced 25% for being overlay, and then they’re already five years old
- 25*.75-5: 13.75
- 2012+trunc(#): 2025
Or, calculate the area of a circle:
- diameter = 9
- radius = diameter/2
- pi*radius^2: 63.6174
Doing this I also got carried away and added ceiling and floor to the mix, because just using trunc isn’t always exactly right. Using either of those extra functions will make the pad incompatible with MathPad, however.
- July 6, 2012: Yet Another Pad Calculator
-
Jose Cueva has written a very rough pad interface for OS X and Windows, inspired by Mark Widholm’s MathPad. His YAPC looks like it does just calculations, but it seems to work well. And it works fine in Mac OS X 10.7.4 Lion.
- SilverService and Snow Leopard: Rob Hague at Rob Hague’s Blog
- “I’ve dusted off the (now pretty ancient) source code, and got it compiling under the latest XCode. It basically works, but has at least one major interface bug, and one more minor problem that has been present since the start. I plan to look into these over the next few weeks, with the aim of producing an updated version with bug fixes but no new features.”
More calculators
- iOS Handwriting calculator that solves equations
- MyScript Calculator is a calculator program for the iPhone and iPad that lets you write your calculations by hand—and you will even solve them for you!
- MathPad is back!
- MathPad 3.0.4 now supports Mac OS X 10.7 and up.
- Yet Another Pad Calculator
- YAPC is a very rough math pad, but it does work on Mac OS X 10.7.