2 回答
TA贡献1796条经验 获得超4个赞
bcdiv
bcdiv ( string $dividend , string $divisor [, int $scale = 0 ] ) : string参数
dividend
股息,作为一个字符串。
divisor
除数,作为字符串。
scale
此可选参数用于设置结果中小数点后的位数。如果省略,它将默认使用该bcscale()
函数全局设置的比例,如果尚未设置,则回退到 0。
如您所见,bcdiv
第三个参数不是用于 rounding,而是用于 scale,这意味着它只保留该位数。
Alix Axel对这个特定问题有一个很好的 Q/A ,您可以在这里看到“如何计算上限、下限和四舍五入 bcmath 数字?” .
在他的回答中,他有一个自定义函数bcround
,可以按照您的预期进行舍入:
function bcround($number, $precision = 0)
{
if (strpos($number, '.') !== false) {
if ($number[0] != '-')
return bcadd($number, '0.' . str_repeat('0', $precision) . '5', $precision);
return bcsub($number, '0.' . str_repeat('0', $precision) . '5', $precision);
}
return $number;
}
$val1 = 599.60;
$val2 = 60;
var_dump(bcround(bcdiv($val1, $val2, 10), 0));
// string(2) "10"
var_dump(bcround(bcdiv($val1, $val2, 10), 2));
// string(4) "9.99"
var_dump(bcround(bcdiv($val1, $val2, 10), 1));
// string(4) "10.0"
处理货币数字的正确方法
我不确定您的数字是否指的是价格和货币,但如果是这种情况,那么处理货币计算的最佳方法是将所有值设为美分并使用整数进行数学运算。
对于您的示例:
$val1 = 59960; // 59960 cents == 599.60
$val2 = 6000; // 6000 cents == 60.00
var_dump($val1 / $val2);
// float(9.9933333333333)
var_dump(round($val1 / $val2, 0));
// float(10)
var_dump(round($val1 / $val2, 2));
// float(9.99)
var_dump(round($val1 / $val2, 1));
// float(10)
TA贡献2080条经验 获得超4个赞
因为我在多个类中使用BCMath计算并且我没有足够的时间将所有带有浮点数的地方重写为整数,所以我决定创建简单的特征。它用四舍五入的值解决了我所有的问题。这是特征代码:
trait FloatCalculationsTrait
{
/**
* Default precision for function results
*
* @var integer
*/
protected $scale = 2;
/**
* Default precision for BCMath functions
*
* @var integer
*/
protected $bcMathScale = 10;
/**
* Rounding calculation values, based on https://stackoverflow.com/a/60794566/3212936
*
* @param string $valueToRound
* @param integer|null $scale
* @return float
*/
protected function round(string $valueToRound, ?int $scale = null): float
{
if ($scale === null) {
$scale = $this->scale;
}
$result = $valueToRound;
if (strpos($valueToRound, '.') !== false) {
if ($valueToRound[0] != '-') {
$result = bcadd($valueToRound, '0.' . str_repeat('0', $scale) . '5', $scale);
} else {
$result = bcsub($valueToRound, '0.' . str_repeat('0', $scale) . '5', $scale);
}
}
return $result;
}
/**
* Add floats
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function add(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
$result = bcadd($firstElement, $secondElement, $this->bcMathScale);
return $this->round($result, $scale);
}
/**
* Substract floats
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function substract(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
$result = bcsub($firstElement, $secondElement, $this->bcMathScale);
return $this->round($result, $scale);
}
/**
* Alias for `substract` function
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function sub(?float $firstElement, float $secondElement, ?int $scale = null): float
{
return $this->substract($firstElement, $secondElement, $scale);
}
/**
* Multiply floats
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function multiply(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
$result = bcmul($firstElement, $secondElement, $this->bcMathScale);
return $this->round($result, $scale);
}
/**
* Alias for `multiply` function
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function mul(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
return $this->multiply($firstElement, $secondElement, $scale);
}
/**
* Divide floats
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function divide(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
$result = bcdiv($firstElement, $secondElement, $this->bcMathScale);
return $this->round($result, $scale);
}
/**
* Alias for `divide` function
*
* @param float|null $firstElement
* @param float|null $secondElement
* @param integer|null $scale
* @return float
*/
protected function div(?float $firstElement, ?float $secondElement, ?int $scale = null): float
{
return $this->divide($firstElement, $secondElement, $scale);
}
}
在这里您可以查看结果:http ://sandbox.onlinephpfunctions.com/code/5b602173a1825a2b2b9f167a63646477c5105a3c
- 2 回答
- 0 关注
- 111 浏览
添加回答
举报