在PHP中处理大量数据
若要按照使用大数字(100000+)时的要求使用,需要进行一些非常大的计算 当我将两个大数字相乘(例如:62574和62574)时,PHP似乎将结果转换为浮点数。获取返回奇怪值的的模数值在PHP中处理大量数据,php,bignum,Php,Bignum,若要按照使用大数字(100000+)时的要求使用,需要进行一些非常大的计算 当我将两个大数字相乘(例如:62574和62574)时,PHP似乎将结果转换为浮点数。获取返回奇怪值的的模数值 $x = 62574 * 62574; var_dump($x); // float(3915505476) ... correct var_dump($x % 104659); // int(-72945) ... wtf. 有没有办法让PHP正确执行这些计算?或者,是否有另一种方法可以
$x = 62574 * 62574;
var_dump($x); // float(3915505476) ... correct
var_dump($x % 104659); // int(-72945) ... wtf.
有没有办法让PHP正确执行这些计算?或者,是否有另一种方法可以找到适用于大数的模数值?我建议您试试。如果这不起作用,您可以使用添加用于大整数计算的C/C++代码,并将其链接到您的代码中。您看了吗?php在32位平台上存在整数超过2^31-1的问题
var_dump(bcmod("$x", '104659') ); // string(4) "2968"
出于某种原因,PHP中有两个标准库处理任意长度/精度数字:和。我个人更喜欢GMP,因为它更新鲜,API更丰富 基于GMP,我已经实现了存储和处理货币金额(如100.25美元)。那里有很多mod计算,没有任何问题。使用非常大的数字进行测试。使用此选项
$num1 = "123456789012345678901234567890";
$num2 = "9876543210";
$r = mysql_query("Select @sum:=$num1 + $num2");
$sumR = mysql_fetch_row($r);
$sum = $sumR[0];
我找到了另一个解决方案,但数字将存储为字符串。一旦您将其转换回数值,您将受限于底层平台的精度。在32位平台上,可以表示为int类型的最大int为2147483647:
/**
* @param string $a
* @param string $b
* @return string
*/
function terminal_add($a, $b){
return shell_exec('echo "'.$a.'+'.$b.'"|bc');
}
// terminal_add("123456789012345678901234567890", "9876543210")
// output: "123456789012345678911111111100"
我为您编写了一个非常小的代码,在遇到大数字的情况下肯定会起作用-
<?php
$x = gmp_strval(gmp_mul("62574","62574")); // $x="3915505476"
$mod=gmp_strval(gmp_mod($x,"104659")); //$mod="2968"
echo "x : ".$x."<br>";
echo "mod : ".$mod;
/* Output:
x : 3915505476
mod : 2968
*/
?>
您只需使用字符串来存储大数字,并使用PHP中的GMP函数对其进行操作
您可以在这里的官方PHP手册中查看一些良好的GMP功能-
Nice(讽刺)…没有任何文档!注意:如您所见,这是因为%
使用整数包装器。PHP的整数实现存在致命缺陷,1)完全依赖于平台(endianess和位大小)2)PHP只使用有符号整数,3)超出有符号整数的范围,致命的部分开始发挥作用,因为它会将结果转换为浮动。这意味着,如果你在32位系统上执行1+2147483647,你将得到一个浮点,这使得打包二进制数据“非常有趣”。现代用户可能会发现,他们无法在闪亮的现代64位机器上使用问题中的数字重现这种行为——事实上,当他们var_dump($x)时,他们可能会发现
它们得到的是整数,而不是浮点数。但是,如果他们尝试执行$x=PHP\u INT\u MAX+1
而不是$x=62574*62574代码>,他们将能够成功地重现其余的疯狂。也许PHP技术已经有所改进,或者它是一个不同的PHP设置,但你的代码你认为这有什么作用?-1;这个答案无法理解OP的问题,更不用说解决它了。在高于PHP_INT_MAX的浮点值上调用intval()
,将得到非常不正确的结果。对于62574*62574
(2008年问题中使用的数字)来说,唯一的原因是,在更现代的PHP构建中,该数字低于PHP_INT_MAX
——但出于同样的原因,提问者的原始代码在现代系统上运行良好,不需要对其进行更改。增加你的平方数,直到你最后被迫将$x变成一个浮点,你就会意识到这是错误的。代码显示了intval和sprintf之间的区别——通过sprintf提供了一个潜在的解决方案。对不起,SQL server是一个SQL server,而不是一个计算器。@GordonM,您是否从未在Delphi中使用ListBox对字符串进行过排序?@Namek鉴于Delphi的受欢迎程度,我怀疑在过去10年中是否有人使用过它。@Namek还有其他方法对字符串进行排序吗?;)@GordonM请检查Lazarus项目,你会惊讶于Pascal社区今天的表现:)GMP只适用于整数,而BC Math适用于浮点数。@Fleshgrinder不,BC Math支持任意精度的定点。浮点数是完全不同的。你完全正确,是的。上面的评论很快,我只想说GMP==int&&BC==float
:)这不是一个很好的答案,因为这里没有例子。这是一个令人印象深刻的想法。添加你的答案的描述
<?php
$x = gmp_strval(gmp_mul("62574","62574")); // $x="3915505476"
$mod=gmp_strval(gmp_mod($x,"104659")); //$mod="2968"
echo "x : ".$x."<br>";
echo "mod : ".$mod;
/* Output:
x : 3915505476
mod : 2968
*/
?>
<?php
function add($int1,$int2){
$int1 = str_pad($int1, strlen($int2), '0', STR_PAD_LEFT);
$int2 = str_pad($int2, strlen($int1), '0', STR_PAD_LEFT);
$carry = 0;
$str = "";
for($i=strlen($int1);$i>0;$i--){
$var = $int1[$i-1] + $int2[$i-1] + $carry;
$var = str_pad($var, 2, '0', STR_PAD_LEFT);
$var = (string) $var;
$carry = $var[0];
$str = $str . $var[1];
}
$res = strrev($str.$carry);
echo ltrim($res,"0");
}
add($int1,$int2);
?>