PDA

View Full Version : ToMetric()

mjones74
Dec 9th, 2006, 06:51 AM
Hi friends, here is a sloppy function that converts an input value to metric power notation. It's limited to +/-2 billion or so and seems to work ok, but might contain bugs. Suggestions appreciated. :D

<?php

// integer to metric units notation "2125314" --> "2.13M"
function ToMetric(\$in) {
if ((\$in >= 1000000000) || (\$in <= -1000000000)) {
\$divs = 1000000000;
\$mul = 'G';
} elseif ((\$in >= 1000000) || (\$in <= -1000000)){
\$divs = 1000000;
\$mul = 'M';
} elseif ((\$in >= 1000) || (\$in <= -1000)) {
\$divs = 1000;
\$mul = 'k';
} elseif ((\$in >= 1) || (\$in <= -1)) {
\$divs = 1;
\$mul = '';

} elseif (\$in >= 0.001) {
\$divs = 0.001;
\$mul = 'm';
} elseif (\$in >= 0.000001) {
\$divs = 0.000001;
\$mul = 'u';
} elseif (\$in >= 0.000000001) {
\$divs = 0.000000001;
\$mul = 'n';
} else {
return 0; // only thing left :)
}
\$end = (\$in / \$divs); // result is ones-based, i.e. 1.95252242
\$end = round(\$end,2); // 1.96
\$end = strval(\$end); // "1.96"
\$end = \$end.\$mul; // "1.96M"
return \$end;
}

// test
echo '<pre>';
echo '2 Gigabytes : ' . ToMetric(2097152000) . 'B<br>';
echo '2,204,222 Ohms : ' . ToMetric(2204222) . '<br>';
echo '1,245 Hertz : ' . ToMetric(1245) . 'Hz<br>';
echo '-5,041 Volts : ' . ToMetric(-5041) . 'V<br>';
echo '0.00144 Watts : ' . ToMetric(0.00144) . 'W<br>';
echo '-584,046 Amps : ' . ToMetric(-584046) . 'A<br>';
echo '0.0000001592s : ' . ToMetric(0.0000001592) . 's<br>';
echo '15 Beakers : ' . ToMetric(15) . ' Flasks<br>';
echo '-2 Students : ' . ToMetric(-2) . ' F\'s<br>';
echo '0 Ice cubes : ' . ToMetric(0) . ' Frozen Things<br>';
echo '</pre>';

?>

Results:

2 Gigabytes : 2.1GB
2,204,222 Ohms : 2.2M
1,245 Hertz : 1.25kHz
-5,041 Volts : -5.04kV
0.00144 Watts : 1.44mW
-584,046 Amps : -584.05kA
0.0000001592s : 159.2ns
-2 Students : -2 F's
0 Ice cubes : 0 Frozen Things

firepages
Dec 9th, 2006, 11:46 PM
A quick explanation of what metric power notation actually is may have helped ;) I was about to delete this post then it finally dawned on me ... I am getting on now but I am not the only slow one here ;)

PS : echo ToMetric('1000000000'); gives 1G ... which is right for teaspoons but (technically) wrong for bytes, perhaps some reference to base might help?

marek_mar
Dec 10th, 2006, 01:21 AM
Byte sizes are base 2 and have different names and abbreviations to distignuish them from the base 10 names and abbreviations. For example
1 GiB (gibibyte) is 1073741824bytes (2^30).
This is a relatively new standard and is not directly connected to the SI system (SI is not used in about 3 countries).

BTW the script is missing some prefixes: deca (da) 10^1, hecto (h) 10^2, deci (d) 10^-1 and centi (c) 10^-2.

mjones74
Dec 17th, 2006, 06:01 PM
Hi, here's an updated version. Are the new prefixes correct? Yes the GB example was probably not the best example. Thanks for looking.

<?php
// integer to metric power notation "2125314" --> "2.13M"
function ToMetric(\$in) {
if ((\$in >= 1000000000) || (\$in <= -1000000000)) {
\$divs = 1000000000;
\$mul = 'G';
} elseif ((\$in >= 1000000) || (\$in <= -1000000)){
\$divs = 1000000;
\$mul = 'M';
} elseif ((\$in >= 1000) || (\$in <= -1000)) {
\$divs = 1000;
\$mul = 'k';
} elseif ((\$in >= 100) || (\$in <= -100)) {
\$divs = 100;
\$mul = 'h';
} elseif ((\$in >= 10) || (\$in <= -10)) {
\$divs = 10;
\$mul = 'da';

} elseif ((\$in >= 1) || (\$in <= -1)) {
\$divs = 1;
\$mul = '';

} elseif (\$in >= 0.1) {
\$divs = 0.1;
\$mul = 'd';
} elseif (\$in >= 0.01) {
\$divs = 0.01;
\$mul = 'c';
} elseif (\$in >= 0.001) {
\$divs = 0.001;
\$mul = 'm';
} elseif (\$in >= 0.000001) {
\$divs = 0.000001;
\$mul = 'u';
} elseif (\$in >= 0.000000001) {
\$divs = 0.000000001;
\$mul = 'n';
} else {
return '0'; // only thing left is zero
}
return strval(round((\$in / \$divs),2)).\$mul;
}
?>

ralph l mayo
Dec 18th, 2006, 06:16 PM
A long chain of if cases is usually an indicator that a lookup table may be useful, eg:

function to_metric(\$num)
{
if (\$num == 0)
{
return 0;
}
\$postfixes = array(
'G' => 1000000000,
'M' => 1000000,
'k' => 1000,
'h' => 100,
'da' => 10,
'' => 1,
'd' => 0.1,
'c' => 0.01,
'm' => 0.001,
'u' => 0.000001,
'n' => 0.000000001
);
foreach (\$postfixes as \$postfix => \$factor)
{
if (\$num >= \$factor)
{
return round(\$num / \$factor, 2) . \$postfix;
}
}
return \$num;
}

After refactoring like that, all you have to do next time some wiseguy suggests a new suffix is add it to the table.

marek_mar
Dec 18th, 2006, 06:43 PM
After refactoring like that, all you have to do next time some wiseguy suggests a new suffix is add it to the table.
I heard that!

ralph l mayo
Dec 18th, 2006, 06:49 PM
I heard that!
hehe :p

mjones74
Dec 19th, 2006, 06:21 PM
Beautiful Ralph, thanks! :-)