Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!swrinde!ucsd!helios.ee.lbl.gov!austern@ux5.lbl.gov From: austern@ux5.lbl.gov (Matt Austern) Newsgroups: comp.sys.handhelds Subject: Generalized unit conversion on the HP48sx Message-ID: <6340@helios.ee.lbl.gov> Date: 1 Aug 90 17:40:14 GMT Sender: usenet@helios.ee.lbl.gov Reply-To: austern@ux5.lbl.gov (Matt Austern) Organization: Lawrence Berkeley Laboratory (theory group) Lines: 99 X-Local-Date: 1 Aug 90 10:40:14 PDT A few days ago, I posted an article saying that I'd written a generalized form of CONVERT for the unit systems that are generally used in high-energy physics, where we set hbar=c=1. I asked for suggestions about a better way to do one step, which I was doing by a horrible kludge. One person suggested using one of the MATCH commands. I played with them for a while, but couldn't find a way to make them do what I needed. Other than that, I have received no suggestions. I have, however, received several requests for my code, so here it is, kludge and all. The method of performing generalized unit conversion is to find out how many powers of hbar and c are needed to make the units compatible, do the multiplication, and then convert. Finding out how many powers are necessary ought to be simple: take the ratio between the two unit objects, then find out how many powers of each base unit are in that ratio. The rest is a little algebra. The hard part is finding out how many powers of each base unit there are. That information must be there, somewhere, in the internal representation of a unit object, but I couldn't find any way to get at it. So here's the disgusting part: I use UBASE to convert the unit object to base units, then convert it to a string and do string searches. There must be a better way... Here's the program, finally: \<< DUP2 SWAP / ULST @@@ CVT \-> u1 u2 rat \<< h rat 2 GET ^ c rat 1 GET rat 2 GET2 * - ^ * u1 * u2 IFERR CONVERT THEN DROP2 u1 u2 #2818d DOERR END \>> \>> 'CVT' STO \<< UBASE \->STR DUP SIZE \-> s l @@@ ULST \<< s "/" POS IF DUP 0 == THEN DROP l 1 + END \-> sl \<< s sl "m" CNUN s sl "kg" CNUN s sl "s" CNUN s sl "A" CNUN s sl "K" CNUN s sl "cd" CNUN s sl "mol" CNUN 7 \->LIST \>> \>> \>> 'ULST' STO \<< \-> s sp un @@@ UCNT \<< s u POS \-> pos \<< IF pos 0 == THEN 0 ELSE IF s pos 1 + DUP SUB "^" == THEN s pos 2 + DUP IF s pos 3 + DUP SUB NUM DUP "0" NUM \>= SWAP "9" NUM \<= AND @@@ This checks if power is 2 digits. THEN 1 + END SUB STR\-> ELSE 1 END END IF pos sp > THEN NEG END \>> \>> \>> 'UCNT' STO 29979245800_cm/s 'c' STO @@@ c 6.582122E-22_MeV*s 'h' STO @@@ hbar NOTES: (1) UCNT is very incomplete. It won't handle negative powers; however, UBASE never returns negative powers. It also won't handle fractional powers; but, again, UBASE (incorrectly) never returns fractional powers. Another bug (easily fixable, but is it worth the trouble?) is that UCNT can't handle three-digit powers. (2) I don't bother checking in CVT to see if the types of the two unit objects are compatible; it's easier to just let CONVERT discover the error and trap it. (3) The value for 'c' given above is exact; the value for hbar is from the 1988 Review of Particle Properties. (4) As I said above, my implementation of ULST is disgusting. Surely there must be a better way? -- Matthew Austern austern@lbl.bitnet It's not very subtle, but, uh, (415) 644-2618 austern@ux5.lbl.gov neither is blowing up a whole school.