bcmul

(PHP 4, PHP 5, PHP 7, PHP 8)

bcmul将两个任意精度的数字相乘

描述

bcmul(string $num1, string $num2, ?int $scale = null): string

num1 乘以 num2

参数

num1

左操作数,以字符串形式表示。

num2

右操作数,以字符串形式表示。

scale

此可选参数用于设置结果中小数点后的位数。如果省略,它将默认为使用 bcscale() 函数全局设置的比例,或者如果未设置则回退到 0

返回值

以字符串形式返回结果。

变更日志

版本 描述
8.0.0 scale 现在可以为空。
7.3.0 bcmul() 现在返回具有请求比例的数字。以前,返回的数字可能会省略尾随的小数零。

示例

示例 #1 bcmul() 示例

<?php
echo bcmul('1.34747474747', '35', 3); // 47.161
echo bcmul('2', '4'); // 8
?>

注释

注意:

在 PHP 7.3.0 之前,bcmul() 可能会返回一个小数点后位数少于 scale 参数指示的结果。这仅在结果不需要 scale 允许的全部精度时发生。例如

示例 #2 bcmul() 比例示例

<?php
echo bcmul('5', '2', 2); // 输出 "10",而不是 "10.00"
?>

参见

  • bcdiv() - 将两个任意精度的数字相除

添加注释

用户贡献的注释 4 个注释

10
Nitrogen
15 年前
我做了这个来将无限大小的整数相乘(意味着没有小数点)。
这对于那些没有 BCMath 扩展的人可能会有用。

<?php

function Mul($Num1='0',$Num2='0') {
// 检查两个数是否都是纯数字
if(!preg_match("/^\d+$/",$Num1)||!preg_match("/^\d+$/",$Num2)) return(0);

// 从数字开头删除零
for($i=0;$i<strlen($Num1);$i++) if(@$Num1{$i}!='0') {$Num1=substr($Num1,$i);break;}
for(
$i=0;$i<strlen($Num2);$i++) if(@$Num2{$i}!='0') {$Num2=substr($Num2,$i);break;}

// 获取两个数字的长度
$Len1=strlen($Num1);
$Len2=strlen($Num2);

// $Rema 用于存储计算结果,$Rema2 用于进位
$Rema=$Rema2=array();

// 我们首先创建一个 $Len1 行 $Len2 列的表格(数组)
for($y=$i=0;$y<$Len1;$y++)
for(
$x=0;$x<$Len2;$x++)
// 我们使用经典的格子乘法方法来计算乘法..
// 这将把 $Num1 中的每个数字乘以 $Num2 中的每个数字并进行相应的存储
@$Rema[$i++%$Len2].=sprintf('%02d',(int)$Num1{$y}*(int)$Num2{$x});

// 遍历每个存储的数字
for($y=0;$y<$Len2;$y++)
for(
$x=0;$x<$Len1*2;$x++)
// 将数字按照格子乘法的对角线方向进行累加
@$Rema2[Floor(($x-1)/2)+1+$y]+=(int)$Rema[$y]{$x};

// 反转结果
$Rema2=array_reverse($Rema2);

// 再次遍历所有结果
for($i=0;$i<count($Rema2);$i++) {
// 反转此项,拆分,保留第一位,将其他位向下传递
$Rema3=str_split(strrev($Rema2[$i]));
for(
$o=0;$o<count($Rema3);$o++)
if(
$o==0) @$Rema2[$i+$o]=$Rema3[$o];
else @
$Rema2[$i+$o]+=$Rema3[$o];
}
// 将 $Rema2 转换成字符串并反转,这是结果!
$Rema2=strrev(implode($Rema2));

// 为了确保,我们删除结果开头的零并返回
while(strlen($Rema2)>1&&$Rema2{0}=='0') $Rema2=substr($Rema2,1);

return(
$Rema2);
}

$A='5650175242508133742';
$B='2361030539975818701734615584174625';

printf(" Mul(%s,%s); // %s\r\n",$A,$B, Mul($A,$B));
printf("BCMul(%s,%s); // %s\r\n",$A,$B,BCMul($A,$B)); // 内置函数

/*
这将打印类似于以下内容..
Mul(5650175242508133742,2361030539975818701734615584174625);
BCMul(5650175242508133742,2361030539975818701734615584174625);

两者都应该紧跟着答案:
13340236303776981390475700774516825287352418182696750
*/

?>

制作起来很有趣……尽管这比我做的 BCAdd 替代方案花了更长的时间……
但是,对于非常大的数字,内存分配可能是一个问题……如果有人想对我的函数的性能进行基准测试;随意。
享受,
Nitrogen。
7
mgkirs
6 年前
$float = 0.31234144143341;
$float1 = 0.00000000000000000000000000000005;
echo $float, "\n";
//0.31234144143341
echo $float1, "\n";
//5.0E-32
echo $float*$float1, "\n";
//1.5617072071671E-32

<?php
/*bcmul 将浮点数读取为字符串*/
echo bcmul($float, $float1, 32),"\n";
//0
echo bcmul($float, sprint('%.32f',$float1), 32);
//0.000000000000000000000000000000015617072071671;
?>
4
admin at spamhere dot sinfocol dot org
13 年前
好吧,我在服务器上实现 Blake 哈希时遇到了一些问题,因为这不是一台 x64 服务器机器。我编写了一个小函数,利用 BC 库的强大功能来执行按位移位操作。

<?php
echo '左移测试<br />';
bprint('1', decbin(1));
bprint('1 << 32 (失败)', decbin(1 << 32)); // 失败,32 位机器上操作不成功
bprint('shiftleft(1, 32) (成功)', dec2bin(shiftleft('1', '32'))); // decbin 失败,所以我们使用个性化函数,成功

echo '<br />';
echo
'右移测试<br />';
bprint('9223372036854775808', dec2bin('9223372036854775808'));
bprint('9223372036854775808 >> 63 (失败)', decbin(9223372036854775808 >> 63));
bprint('rightshift(9223372036854775808, 63) (成功)', decbin(rightshift('9223372036854775808', '63')));

function
shiftleft($num, $bits) {
return
bcmul($num, bcpow('2', $bits));
}

function
rightshift($num, $bits) {
return
bcdiv($num, bcpow('2', $bits));
}

function
bprint($title, $content) {
echo
$title . '<br />' . str_pad($content, 64, '0', STR_PAD_LEFT) . '<br />' . PHP_EOL;
}

//https://php.net/manual/en/function.decbin.php#99533
function dec2bin($dec) {
// 更适合十进制转二进制的函数。支持更大的值,但不支持符号
for ($b = '', $r = $dec; $r >1;) {
$n = floor($r / 2);
$b = ($r - $n * 2) . $b;
$r = $n; // 当使用更大的值(如 11.435.168.214!)时,$r%2 不准确
}
return (
$r % 2) . $b;
}
?>
0
gar37bic at gmail dot com
11 年前
当使用 printf 打印 bcmath 操作的结果时,使用字符串格式,即 '%s',而不是数字格式,如 '%d' 或 '%f'。例如,如果使用 %d 或 %f,阶乘 (23) 的输出将不正确。

使用 %f 的结果
阶乘 (22) = 1124000727777607680000 (正确)
阶乘 (23) = 25852016738884978212864 (不正确)

使用 %s 的结果
阶乘 (22) = 1124000727777607680000
阶乘 (23) = 25852016738884976640000

使用 echo,这不是问题 - PHP 会正确输出 bcmath 字符串类型。
To Top