Quantcast
Channel: rana_kualuの記事 - Qiita
Viewing all articles
Browse latest Browse all 331

おれがコンピュータに足し算を教えてやろうと思ったらもう知ってた

$
0
0
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カ所の,を消せないものか。
あれがあると結局単に複数の式を並べてるだけになるから、なんというかこう面白くないんだよね。


Viewing all articles
Browse latest Browse all 331

Trending Articles