PHP练习-两个超大数字串相加

2026-03-11 16:25 By "Powerless" 15 0 0

class TitleTwo
{
    private $str1;
    private $str2;

    public function __construct($str1, $str2)
    {
        if (!is_numeric($str1)) {
            throw new \InvalidArgumentException('第一个参数必须是数字');
        }
        if (!is_numeric($str2)) {
            throw new \InvalidArgumentException('第二个参数必须是数字');
        }
        $this->str1 = $str1;
        $this->str2 = $str2;
    }

    /**
     * 方法一:多位相加
     * 每次处理 8 位数字,平衡效率和溢出风险
     * @return string 返回两个字符串相加后的结果
     */
    public function sumStr1()
    {
        $chunkSize = 8;
        $base = pow(10, $chunkSize);
        $len1 = strlen($this->str1);
        $len2 = strlen($this->str2);
        $maxLen = max($len1, $len2);

        $str1 = str_pad($this->str1, ceil($maxLen / $chunkSize) * $chunkSize, '0', STR_PAD_LEFT);
        $str2 = str_pad($this->str2, ceil($maxLen / $chunkSize) * $chunkSize, '0', STR_PAD_LEFT);

        $result = [];
        $carry = 0;
        $chunks1 = str_split($str1, $chunkSize);
        $chunks2 = str_split($str2, $chunkSize);
        $totalChunks = count($chunks1);
        for ($i = $totalChunks - 1; $i >= 0; $i--) {
            $num1 = (int)$chunks1[$i];
            $num2 = (int)$chunks2[$i];
            $sum = $num1 + $num2 + $carry;

            if ($sum >= $base) {
                $carry = 1;
                $sum -= $base;
            } else {
                $carry = 0;
            }

            $result[] = str_pad((string)$sum, $chunkSize, '0', STR_PAD_LEFT);
        }

        if ($carry > 0) {
            $result[] = '1';
        }
        $finalResult = ltrim(implode('', array_reverse($result)), '0');
        return $finalResult === '' ? '0' : $finalResult;
    }

    /**
     * 方法二:补零对齐法
     * 先将两个字符串补齐到相同长度,然后逐位相加
     * @return string 返回两个字符串相加后的结果
     */
    public function sumStr2()
    {
        $len1 = strlen($this->str1);
        $len2 = strlen($this->str2);
        $maxLen = max($len1, $len2);
        $str1 = str_pad($this->str1, $maxLen, '0', STR_PAD_LEFT);
        $str2 = str_pad($this->str2, $maxLen, '0', STR_PAD_LEFT);
        $result = '';
        $carry = 0;
        for ($i = $maxLen - 1; $i >= 0; $i--) {
            $sum = $str1[$i] + $str2[$i] + $carry;
            $result = ($sum % 10).$result;
            $carry = intval($sum / 10);
        }
        if ($carry > 0) {
            $result = $carry.$result;
        }
        return $result;
    }

    /**
     * 方法三:从最低位开始逐位相加
     * 从最低位开始逐位相加,并记录进位
     * @return string 返回两个字符串相加后的结果
     */
    public function sumStr3()
    {
        $len1 = strlen($this->str1) - 1;
        $len2 = strlen($this->str2) - 1;
        $result = [];
        $carry = 0;

        while ($len1 >= 0 || $len2 >= 0 || $carry > 0) {
            $digit1 = $len1 >= 0 ? (int)$this->str1[$len1] : 0;
            $digit2 = $len2 >= 0 ? (int)$this->str2[$len2] : 0;
            $sum = $digit1 + $digit2 + $carry;
            $result[] = $sum % 10;
            $carry = intval($sum / 10);
            $len1--;
            $len2--;
        }

        return implode('', array_reverse($result));
    }
}

try {
    $index = new TitleTwo('21543655', '4332656442');
    $res1 = $index->sumStr1();
    echo "方法一相加结果:";
    var_dump($res1);
    $res2 = $index->sumStr2();
    echo "方法二相加结果:";
    var_dump($res2);
    $res3 = $index->sumStr3();
    echo "方法三相加结果:";
    var_dump($res3);
} catch (\InvalidArgumentException $e) {
    echo "错误:" . $e->getMessage();
}

方法一相加结果:string(10) “4354200097”
方法二相加结果:string(10) “4354200097”
方法三相加结果:string(10) “4354200097”

评 论

View in WeChat

Others Discussion

  • 一些常见的基础概念
    Posted on 2018-11-28 19:10
  • HTTP头中隐藏PHP版本号
    Posted on 2021-01-11 16:38
  • QPS、TPS、RT、吞吐量到底是什么
    Posted on 2020-02-02 01:15
  • MySQL事务介绍
    Posted on 2019-06-05 18:14
  • 能创建多少个 TCP 连接?
    Posted on 2021-08-02 16:00
  • MySQL中的行级锁,表级锁,页级锁
    Posted on 2018-08-25 11:00
  • 2018年云计算热词
    Posted on 2019-06-12 18:19
  • PHP 基金会来啦!
    Posted on 2022-10-08 17:40