【问题标题】:Best method to deal with numbers? Getting and changing individual digits处理数字的最佳方法?获取和更改单个数字
【发布时间】:2011-08-01 11:52:40
【问题描述】:

我想取一个 1 到 17 位的数字,然后通过一系列逻辑循环来改变数字的各个数字。我需要能够做到以下几点:

1) 一种快速了解数字中有多少位的方法。有没有一个好的(有效的)php 方法来做到这一点?以 10 为基数是最好的方法吗?或者也许把它变成一个字符串并询问长度?

2) 接下来,我需要知道每个数字中的数字。我是否应该继续对数字执行 % 10 以解析每个数字(这样做也有助于通过在循环中添加计数来解决问题 1)?

3) 最后,我需要一个好方法来更改数字的各个数字。我应该使用正则表达式吗?还是我应该通过将各种数字加在一起来建立一个新数字,每个数字代表一个数字(例如 1 + 30 + 400 + 2000 + 6000 = 62431)?我想我也可以使用与上一个示例相同的方法来调整原始数字,方法是添加/减去原始数字,将每个数字调整为我想要的数字。

如果您觉得其他方法更快,请告诉我解决我的问题的其他方法。效率是关键。

【问题讨论】:

  • 既然您已经对 1 和 2 有了一些想法,为什么不自己尝试对它们进行基准测试呢?
  • 我实际上并不擅长基准测试(基本上不知道)。 php中有什么好的工具可以做到这一点吗?或者我应该在一百万次循环之后输出时间戳?感谢您的帮助。
  • 查看我的帖子以获取简单的基准测试示例。我已经检查了数字长度方法。使用 common log 比 string cast 和 substr 快 3 倍。
  • 如果你想让它完全可靠,你需要使用字符串。
  • 要获得整数i的长度,一种快速的方法(在C语言中)是:n=1; if(i>=100000000){n+=8;i/=100000000;} if(i>=10000){n+=4;i/=10000;} if(i>=100){n+=2;i/=100} if(i>=10){n+=1;}

标签: performance math numbers


【解决方案1】:

我决定写一个答案,因为当前接受的答案是完全错误的。 double 数字的相对精度约为 1E-16。这不是 PHP 的限制,这是 IEEE 754 double 的固有特性。因此,如果要操作双精度数的第 17 位,无论数字的大小是多少,使用对数和执行算术运算都是行不通的。您需要做的是将数字转换为字符串,操作字符串中的数字并从字符串中显示出来,而不是将其转换回double

【讨论】:

    【解决方案2】:

    您可以通过以下方式更改数字中数字的值:

    function numlen($number) { return strlen($number); }
    
    function numAt($number, $index) { return substr($number, $index, 1); }
    
    function changeNumAt($number, $index, $newDigit) {
        return substr_replace($number, $newDigit, $index, 1);
    }
    

    对于您的情况,使用数字作为字符串进行一次数字更改是最有意义的。为了节省时间,如果您要更改多个数字,您应该将数字解析为一个数字数组。如果您需要帮助,请在 cmets 中告诉我。


    简单的基准测试示例:

    $start = microtime(true); //Log the start timestamp (including microseconds)
    //Do stuff to benchmark
    $end = microtime(true); //Log the end timestamp (including microseconds)
    echo ((string)($end-$start))."seconds \n";
    

    使用microtime(true) 获取以微秒为浮点数的时间戳(这就是 true 的用途)。获取动作前后的时间,减去它们得到总时间。

    【讨论】:

    • 您的代码示例不适用于标准浮点数。
    • 我不明白为什么不这样做。使用通用日志的长度将起作用(因为不需要计算小数)。 numAt() 适用于小数点前的数字。 changeNumAt() 将用于更改小数点前的值。您唯一不能做的就是更改小数点后的数字(如果 OP 需要,我可以为此修改我的代码)。
    • 由于浮点数的精度有限,它不起作用。在 1000000000000 上尝试您的代码并将其修改为 1000000000001。
    • 不,这是 64 位双精度的限制。您在 Java、C 或 C++ 中也会遇到同样的问题(除非您使用具有扩展精度的非标准双精度)。而在处理1.1234567890123456时也会出现同样的问题。 OP 明确询问有关操作 1 到 17 位数字的数字。鉴于浮点数的性质,小数点的位置无关紧要。
    • @quant_dev 我已经更新了我的代码以避免出现您所建议的问题。感谢您指出了这一点。我知道浮点整数的问题,但不知道它适用于这种情况。再次感谢!
    猜你喜欢
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 2022-11-27
    • 2016-05-12
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2013-03-27
    相关资源
    最近更新 更多