echogmp_add('2345760293460295683704558703456102394871348756109347501936410934756102913874187344541930193470934875','7947618927365019364019257691823461928734634570193248703473987562093471093576293478628949398873429857');// 10293379220825315047723816395279564323605983326302596205410398496849574007450480823170879592344364732
はい。
まあ、これだけだとアレなので、GMPを使わずaddBigIntをもう少し簡単に書けないか検討してみることにします。
functionaddBigInt(string$a,string$b):string{$a=strrev($a);$b=strrev($b);$ret='';for($i=$c=0;isset($a[$i])||isset($b[$i]);$i++){$tmp=($a[$i]??0)+($b[$i]??0)+$c;$c=$tmp>9;$ret[$i]=$tmp%10;}if($c){$ret[$i]=1;}returnstrrev($ret);}
とりあえず何も考えずに書いたらこんなかんじになりました。
単に1桁毎に順番に計算しているだけですね。
strrevが3回も入ってたりisset判定が残念な感じだったりif($c)
とかわざわざ書いてたり微妙なのでどうにかしたいところです。
functionaddBigInt(string$a,string$b):string{$i=max(strlen($a),strlen($b));$a=str_pad($a,$i,0,STR_PAD_LEFT);$b=str_pad($b,$i,0,STR_PAD_LEFT);$ret='';for($c=0,$i--;$i>=0;$i--){$tmp=($a[$i]??0)+($b[$i]??0)+$c;$c=$tmp>9;$ret[$i]=$tmp%10;}if($c){return'1'.$ret;}return$ret;}
strrevを消して逆順に計算することとし、また桁数を揃えることで毎回issetで条件判定せずに済むようにしました。
しかしstr_padのもっさり感と、if($c)
がやっぱり消せないのが惜しいところです。
最終式
functionaddBigInt(string$a,string$b):string{for($a=str_pad($a,$i=max(strlen($a),strlen($b),$c=0),0,0),$b=$r=str_pad($b,$i--,0,0);$i>=0;$c=($t=$a[$i]+$b[$i]+$c)>9,$r[$i--]=$t%10);return$c?'1'.$r:$r;}
単に詰めただけです。
エラーを出さない条件では、このあたりが限界でした。
ちなみにエラーを許容するなら、strrevを使ったほうが短くなります。
エラー出る
functionaddBigInt(string$a,string$b):string{for($f=strrev,$l=max(strlen($a=$f($a)),strlen($b=$r=$f($b)));$i<$l;$c=($t=$a[$i]+$b[$i]+$c)>9,$r[$i++]=$t%10);return($c?1:'').$f($r);}
最終式の問題点
max(strlen($a))
と入力値を元にした数値を使っているので、PHP_INT_MAX桁を超える文字列だと正常に動かなくなります。
その前にメモリとかが死にそうですが。
あと0未満の値は正しく計算できません。
これは元の関数からしてそうなので仕様としておきます。
感想
残った2カ所の,
を消せないものか。
あれがあると結局単に複数の式を並べてるだけになるから、なんというかこう面白くないんだよね。