为什么 strlen 在特定数字中不起作用

Why strlen doesn't work in a paticular digit

我做了这个功能。它似乎在工作,但是当涉及到 20 位数字时,return 值为 19。我想知道为什么会发生这个问题..

我的函数

function sumDigits($n) {
    return strlen($n);
}

echo sumDigits(100);  //3
echo sumDigits(1000);  //4
echo sumDigits(12345);  //5
echo sumDigits(1000000000);  //10
echo sumDigits(145874589632);  //12
echo sumDigits(0);  //1
echo sumDigits(12345698745254856320);  //19  <-- Why not 20?

你能帮我解释一下吗?

非常感谢。

因为你的函数参数是整数,超出了限制。 如果你转储它,它实际上显示如下: 1.2345698745255E+19 - 即 19 个字母。

如果您执行以下操作,它将 return 20 - 请注意引号,它将输入声明为字符串。

echo sumDigits("12345698745254856320"); //19 <-- Why not 20? -> now will be 20

首先,我要指出您的函数名称具有误导性,因为您并不是真正对数字的值求和,而是计算 数字。所以我会调用你的函数 countDigits 而不是 sumDigits.

它不适用于大数字的原因是字符串表示将切换为科学记数法,因此您实际上得到的长度是“1.2345698745255E+19”而不是“12345698745254856320”

如果你只对整数感兴趣,用对数会得到更好的结果:

function countDigits($n) {
    return ceil(log10($n));
}

对于有小数点的数字,没有很好的解决办法,因为64位浮点数的精度有限to about 16 significant digits,所以即使你提供更多的数字,尾随的小数点也会被去掉-- 这与你的功能无关,而是与数字本身的精度有关。例如,您会发现这两个文字是相等的:

if (1.123456789123456789123456789 == 1.12345678912345678) echo "equal";

根据 documentationstrlen() 需要一个字符串,因此会发生转换。使用默认设置,您会得到 1.2345698745255E+19:

var_dump((string)12345698745254856320);
string(19) "1.2345698745255E+19"

根本问题是 PHP 将您的整数文字转换为浮点数,因为它超过了 PHP_INT_MAX,因此无法表示为整数:

var_dump(12345698745254856320, PHP_INT_MAX);

64 位 PHP:

float(1.2345698745254857E+19)
int(9223372036854775807)

您可以更改显示设置以避免 E 符号,但此时您已经失去了精度。

将整数存储为固定字节数的计算机语言不允许任意精度。你最好的机会是切换到字符串:

var_dump('12345698745254856320', strlen('12345698745254856320'));
string(20) "12345698745254856320"
int(20)

... 如果您需要实际数学,可以选择使用任意精度库,例如 BCMath or GMP

同样重要的是要考虑到这种问题有时是您的输入数据实际上并不是一个整数而只是一个非常长的纯数字字符串的症状。