Php 获取序列的n位

Php 获取序列的n位,php,loops,Php,Loops,老实说,这是学校的任务。 任务是: 我们需要生成这样的连续数字:12345678910112131415161718192021… 查找第1.000.000位 查找第1.000.000.000位 查找第1.000.000.000.000位 以下是我编写的代码: <?php ini_set('max_execution_time', 3600); ini_set("memory_limit", "512M"); function getDigit($n) { $count =

老实说,这是学校的任务。
任务是:

我们需要生成这样的连续数字:12345678910112131415161718192021…

查找第1.000.000位
查找第1.000.000.000位
查找第1.000.000.000.000位

以下是我编写的代码:

<?php
ini_set('max_execution_time', 3600);
ini_set("memory_limit", "512M");

function getDigit($n)
{
    $count = 1;
    (string) $a = '';
    while (strlen($a) <= $n) {
        $a .= $count;
        $count++;
    }

    $answer = substr($a, ($n - 1), 1);
    echo "The {$n}th digit is: {$answer} <br>";
}

$start = microtime(TRUE); //Start Time Execution

getDigit(1000000000);

$page_time = round(microtime(TRUE) - $start, 3) + '0.02'; // Get the time it took for the page to load
echo $page_time . "<br>"; // Display the total time it took to load the page

您可以迭代数字长度

你知道前九个数字的长度是1,接下来的90个是2,接下来的900个是3

因此,您定义了一个函数:

$index = $input-1;
$rank = 9;
$size = 1;
$offset = 1;
while($index >= $rank*$size) {
    $offset *= 10;
    $index -= $rank*$size;
    $rank *= 10;
    $size++;
}
当算法的该部分结束时,
$size
存储您的号码所在的“组”的号码大小。而
$index
则减少到从该组开始的偏移量。因此,现在我们只需要确定我们正在谈论的数字。这可以通过以下方式实现:

$ith = $index % $size;
$number = $offset+($index-$ith)/$size;
最后,我们写出该数字并得到相应的数字:

$strnum = (string) $number;
echo $strnum{$ith};
或完整版本:

$index = $input-1;
$rank = 9;
$size = 1;
$offset = 1;
while($index >= $rank*$size) {
    $offset *= 10;
    $index -= $rank*$size;
    $rank *= 10;
    $size++;
}
$ith = $index % $size;
$number = $offset+($index-$ith)/$size;
$strnum = (string) $number;
echo $strnum{$ith};

请注意,建议的方法不会枚举所有整数。我们只需确定一组带有k位的数字总共需要多少个字符,如果我们可以跳过这一步,我们只需这样做。接下来,我们计算我们在小组中的确切位置

当然,不能对泛型序列使用此方法,但可以利用建议序列的属性

此方法将在log时间内工作(以输入表示的数字记录),因为在
while
循环中的每次迭代中,秩都以指数方式增加。此外,该方法使用log-内存(它需要存储的字符串),这甚至可以进一步减少

像您这样生成字符串并不是一个好的解决方案:它需要线性时间,最终您的机器在存储整个字符串时会耗尽内存(此外,存储已访问的数字是非常无用的)


在此基础上,您可以预计算所需的值并定义查找表。

我建议您将数字视为字符串,将数字加载到数组中,然后只引用数组位置。您可以预先生成一些常量:所有的单位数(1-9)构成长度为9的字符串。所有的两位数字(10-99)组成一个长度为180的字符串,总数为189。等等你可以在很久很久以后开始搜索。有一种比简单地构造一个巨大的字符串并计算每个数字更有效的方法。你可以用纯数学的方法来解决这个问题。想一想:你可以很容易地计算出有多少个数字有一个数字,有多少有两个数字,依此类推。您可以将数字相加,直到达到目标,然后推断出您的数字。@AndyLester是的,谁在乎性能?@AndyLester:但是
1.000.000.000
实际上永远不会起作用,因为生成的字符串的长度至少为
1.000.000.000
,这会导致存储超过1 GiB的(无用)数据。大多数虚拟机都不允许有这么大的内存。这是一个好的、通用的、几乎是最佳的答案。另一方面,问题只要求3个值。你可以预先计算它们,并有一个由3个输出语句组成的程序。确实,你可以使用LUT,但首先为了生成LUT,你需要某种算法,而且在我看来,如果有人问这样的问题,我想你只是在寻找一种方法如何计算它们?我认为有一个用户使用LUT方法回答了这个问题,我没有投反对票。然而,通过展示如何计算数字,用户可以为所有他期望有用的输入生成LUT。先生,你太棒了。对于第1.000.000.000位,我的代码运行约90秒。但是您的代码可以立即运行。非常感谢您的宝贵知识。谢谢@user3708043:有一个小错误,现在已修复。当然,您需要与大小相乘。@user3708043:second fix,这样的算法在细节上非常困难。