{"id":1858,"date":"2011-08-11T23:35:15","date_gmt":"2011-08-12T05:35:15","guid":{"rendered":"http:\/\/bililite.nfshost.com\/blog\/?p=1858"},"modified":"2011-10-24T09:47:00","modified_gmt":"2011-10-24T15:47:00","slug":"fractions-and-units-in-php","status":"publish","type":"post","link":"https:\/\/bililite.com\/blog\/2011\/08\/11\/fractions-and-units-in-php\/","title":{"rendered":"Fractions and Units in PHP"},"content":{"rendered":"<p>For the <a href=\"\/webservices\">bililite webservices<\/a>, I kept all the data in what I would call \"standard\" American medical units, centimeters for height, kilograms for weight, mmHg for blood pressure, mg\/dl for bilirubin. But lots of doctors use pounds and inches, and it would be nice to allow those as well. I could have separate data entry forms for different units, but I decided it would be easier and more useful to allow units on the numbers. I could allow fractions as well (which some of my medical assistants still insist on recording; 21 5\/8 instead of 21.625. My EMR blows a gasket with that, but <em>my<\/em> program would do better). And then, I could allow mixed units, like a weight of \"6 pounds 5 1\/2 ounces\".<\/p>\r\n<p>I didn't find anything exactly right on the web, but <a href=\"http:\/\/stackoverflow.com\/questions\/1954018\/php-convert-decimal-into-fraction-and-back\/1954324#1954324\">symcbean on stackoverflow<\/a> had a clever idea for evaluating fractions: turn \"2 1\/2\" into \"2+1\/2\" then use <a href=\"http:\/\/php.net\/eval\"><code>eval<\/code><\/a>.<\/p>\r\n<!--more-->\r\n<p><a href=\"\/blog\/blogfiles\/units.php\">Try the code<\/a>.<\/p>\r\n<pre><code class=\"language-php\">function convertCK($usIn){\r\n\t\/\/ convert input numbers with optional units (pounds, inches etc.) to centimeters and kilograms\r\n\t$factors = array(\r\n\t\t'f' =&gt; 30.48, \/\/ feet\r\n\t\t\"'\" =&gt; 30.48,\r\n\t\t'i' =&gt; 2.54, \/\/ inches\r\n\t\t'\"' =&gt; 2.54,\r\n\t\t'p' =&gt; 0.45359237, \/\/ pounds\r\n\t\t'l' =&gt; 0.45359237, \/\/ lb\r\n\t\t'#' =&gt; 0.45359237,\r\n\t\t'o' =&gt; 0.0283495231, \/\/ ounces\r\n\t\t'g' =&gt; 0.001 \/\/ grams\r\n\t);\r\n\t$usIn = trim($usIn);\r\n\t\/\/ turn spaces in mixed numbers to pluses, for the eval hack\r\n\t$usIn = preg_replace ('%(\\d)\\s+(\\d)%', '$1+$2', $usIn);\r\n\tpreg_match_all('%(?&lt;num&gt;[0-9.\/+]+)\\s*(?&lt;unit&gt;\\D*)%', $usIn, $values, PREG_SET_ORDER);\r\n\t$ret = 0;\r\n\tforeach ($values as $value){\r\n\t\t$unit = strtolower($value['unit']{0});\r\n\t\t$factor = isset($factors[$unit]) ? $factors[$unit] : 1;\r\n\t\t$ret += $factor*eval(\"return $value[num];\");\r\n\t}\r\n\treturn $ret;\r\n}<\/code><\/pre>\r\n<p>The code above is simplified by the fact that all the units I care about have unique first letters, but if you wanted more units you could simply add more entries in the <code>factors<\/code> array and make the <code class=\"language-php\">$unit = strtolower($value['unit']{0});<\/code> line more sophisticated. <code>usIn<\/code> is used as a variable name to remind me that it is unsafe&mdash;it may come from user input and has to be sanitized with the regexp before it can be trusted.<\/p>\r\n<p>It allows the American notation for tic marks for feet and inches, since getting that wrong <a href=\"http:\/\/www.youtube.com\/watch?v=Xlf5ucFanpY\">can be disastrous<\/a>.<\/p>","protected":false},"excerpt":{"rendered":"For the bililite webservices, I kept all the data in what I would call \"standard\" American medical units, centimeters for height, kilograms for weight, mmHg for blood pressure, mg\/dl for bilirubin. But lots of doctors use pounds and inches, and it would be nice to allow those as well. I could have separate data entry [&hellip;]","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[12,9],"tags":[],"_links":{"self":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1858"}],"collection":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/comments?post=1858"}],"version-history":[{"count":8,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1858\/revisions"}],"predecessor-version":[{"id":1875,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/posts\/1858\/revisions\/1875"}],"wp:attachment":[{"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/media?parent=1858"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/categories?post=1858"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bililite.com\/blog\/wp-json\/wp\/v2\/tags?post=1858"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}