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

2026-03-11 16:25 By "Powerless" 13 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

  • 浏览器访问网站经历的步骤-Html
    Posted on 2018-11-28 18:48
  • BASE原则
    Posted on 2020-12-17 16:42
  • 程序员年中考试题-段子版
    Posted on 2021-06-23 15:57
  • 前端知识体系精简-Css
    Posted on 2018-03-28 18:34
  • Mysql联合索引的最左前缀匹配原则
    Posted on 2018-08-25 15:00
  • 2016年云计算热词
    Posted on 2019-06-12 17:53
  • PHP没你想的那么差
    Posted on 2021-12-17 15:40
  • 分布式架构之「 数据分布」
    Posted on 2019-11-14 10:00