数据以字符串形式到达
'99 10/32'
或 '99 5/32'
或 '100 5/32'
或 '100 25/32'
等
我需要十进制形式,所以我已经这样做了,但结果并不总是正确的:
...
$priceRaw = '99 5/32'; // ******also could be $priceRaw = 100 15/32, etc
$priceFrac = (str_replace("/32","",substr($priceRaw, -5))/100);
$priceFirst = (substr($priceRaw, 0, 3)*1);
$value = $priceFirst+$priceFrac;
// original code that failed with one digit, e.g. 5/32
// $value=str_replace("/32.","",str_replace(" ",".0",$e->plaintext));
...
按空格分割字符串以获得部分
list($priceFirst, $priceFrac) = explode(' ', $priceRaw);
$priceFrac = (str_replace("/32","",$priceFrac)/100);
echo $value = $priceFirst+$priceFrac;
我会因为
eval
而受到打击,但适用于所有分数。
分割空间并在计算中使用数字:
$priceRaw = '99 5/32';
list($num, $frac) = explode(' ', $priceRaw);
eval("\$result = $num + $frac;");
echo $result; // 99.15625
或将空格替换为
+
并计算:
$calc = str_replace(' ', '+', $priceRaw);
eval("\$result = $calc;");
echo $result; // 99.15625
然后只需
round
或 number_format
或任何您需要的内容。我可能错过了一些重要的东西,因为你的数学很有趣。
或者我们可以走正则表达式路线:
function convFrac($in) {
if( preg_match('#^(\d+)\s+(\d+)/(\d+)$#', $in, $match) ) {
$tmp = array_map('intval', array_slice($match, 1));
return $tmp[0] + $tmp[1] / $tmp[2];
}
throw new \Exception("Badly formatted fraction.");
}
var_dump( convFrac('99 5/32') ); // float(99.15625)
您可以使用“立即调用函数表达式”将格式化字符串解析为其单独的整数部分,然后执行所需的数学运算。如果还有其他方法,我不建议eval()
。我的片段在构建时考虑到了灵活性,因此
32
不是一个硬编码/魔术数字。如果输入字符串中的任何数字可能是浮点值,请使用 %f
而不是 %d
。代码:(演示)
$tests = [
'99 10/32',
'99 5/32',
'100 5/32',
'100 25/32',
];
foreach ($tests as $priceRaw) {
echo (fn($i, $n, $d) => $i + $n / $d)(...sscanf($priceRaw, '%d %d/%d')) . "\n";
}
输出:
99.3125
99.15625
100.15625
100.78125
IIFE 可以作为变量分离出来,具有相同的效果。
$func = fn($i, $n, $d) => $i + $n / $d;
foreach ($tests as $priceRaw) {
echo $func(...sscanf($priceRaw, '%d %d/%d')) . "\n";
}
或更老套/冗长:
function doMath($i, $n, $d) {
return $i + $n / $d;
}
foreach ($tests as $priceRaw) {
echo doMath(...sscanf($priceRaw, '%d %d/%d')) . "\n";
}