【问题标题】:Why strlen doesn't work in a paticular digit为什么 strlen 在特定数字上不起作用
【发布时间】:2021-05-14 07:37:16
【问题描述】:

我做了这个功能。看起来它正在工作,但是当涉及到 20 位数字时,返回值为 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?

你可以请人为我解释一下吗?

非常感谢。

【问题讨论】:

  • 抱歉上次的回复,我刚下班回来!

标签: php strlen


【解决方案1】:

首先,我要指出您的函数名称具有误导性,因为您并没有真正将数字的值相加,而是 计数 数字。所以我会调用你的函数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";

【讨论】:

  • 感谢您对命名和详细解释的建议。我不知道字符串表示会转换为科学记数法,我很高兴知道这一点。我很感激你!
【解决方案2】:

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

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

echo sumDigits("12345698745254856320"); //19 &lt;-- Why not 20? -&gt; now will be 20

【讨论】:

  • 我明白了。感谢您的有用解释和示例!它帮助我理解:)
【解决方案3】:

根据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)

...如果您需要实际的数学运算,还可以选择使用任意精度库,例如 BCMathGMP

同样重要的是要考虑到这类问题有时表明您的输入数据并不是真正的整数,而只是一个非常长的纯数字字符串。

【讨论】:

  • 感谢您的帮助。我只是想解决一个关于 Edabit 的问题,我遇到了这个问题。我在这里问很好,因为你们的回答内容丰富,让我意识到我需要学习什么。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-28
  • 2019-10-11
相关资源
最近更新 更多