任意精度の整数除算


16

任意の大きな整数の除算を実装します。

これはです。

タスクは、任意の精度の整数とその除算を実装するプログラムまたは関数を作成することです。

これを非常に簡単にする多くのことが許可されていないことに注意してください仕様を必ずお読みください

入力

入力として2つのものが与えられます。

  1. 基数10桁の文字列、それを呼び出しますn
  2. 基数10の別の文字列、それを呼び出す m

ことを前提としn>m>0ていることを意味しますが、ゼロ除算に頼まれることはありませんが

出力

もし出力二つの数字、意志Q及びM * Q + R = N及び0 <= R <MR

仕様書

  • 送信は、任意の大きな整数(使用可能なメモリによって制限される)に対して機能します。

  • 外部ライブラリを使用することはできません。I / O用の外部ライブラリが必要な場合は、組み込みライブラリとして扱うことができます。(iostreamなどのようなものを見て)。

  • あなたの言語がこれを簡単にするビルトインを持っているなら、あなたはそれを使わないかもしれません。これには、任意の精度の整数を処理できる組み込み型が含まれます(ただし、これに限定されない場合があります)。

  • 何らかの理由で言語がデフォルトで任意の精度の整数を使用する場合、この機能を使用して、通常64ビットで格納できない整数を表すことはできません。

  • 入力と出力は基数10でなければなりません。メモリへの数値の格納方法や数値の演算方法は関係ありませんが、i / oは10を基数になります。

  • 結果を出力するには15秒あります。これは、反復減算を禁止するためです。

  • ここでの目標は、実際に任意の精度の整数を実装することです。何らかの理由でチャレンジ仕様を遵守し、それらを実装せずにこれを成功させることができれば、私はあなたにとって良いと思う、有効だと思う。

テストケース

  1. この場合、入力は39です!そして30!

入力

n = 20397882081197443358640281739902897356800000000 
m = 265252859812191058636308480000000

出力

Q = 76899763100160
R = 0
  1. n50までのすべての階乗の合計に1を足したものmが、20までの連結数です。

入力

n = 31035053229546199656252032972759319953190362094566672920420940313
m = 1234567891011121314151617181920

出力

q = 25138393324103249083146424239449429
r = 62459510197626865203087816633
  1. n205です!+ 200!。mPeterTaylorが私がサンドボックスに投稿したものをバラバラにしてどれだけ涙を流したかです。

入力

n = 271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000
m = 247

出力

q = 1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000
r = 0;

おそらく、いつかはさらにテストケースを追加するでしょう。

関連する

関連しているように聞こえますが、実際はそうではありません


IOライブラリは外部ライブラリとしてカウントされますか?
ジョンソンスチュワード

@JohnsonStewardそれがどういう意味かわかりませんか?デフォルトでは「はい」ですが、明確にできますか?
リアム

@JohnsonStewardよく、私はそれがあなたがIOしているものに依存していると思いますか?それはコード/コードのライブラリですか?
アシュウィングプタ

1
負の数は許可されますか?
TheConstructor

2
@TheConstructor:ルールから:「n> m> 0と仮定する」ので、負の数は許可されません。
-nimi

回答:


4

Python 2、427バイト

b=S=lambda l:sorted(l)[::-1]
A=lambda a,b,o=0:A(a^b,{n+1for n in[b&a,b-a][o]},o)if b else a
M=lambda a,*b:reduce(A,({n+m for n in a}for m in b))
def D(a,b):
 q=a-a
 while b<=S(a):n=max(a)-b[0];n-=S(M(b,n))>S(a);q|={n};a=A(a,M(b,n),1)
 return q,a
exec"a=b;b=[]\nfor d in raw_input():b=A(M(b,3,1),{i for i in range(4)if int(d)>>i&1})\n"*2
for n in D(a,S(b)):
 s=''
 while n:n,d=D(n,[3,1]);s=`sum(2**i for i in d)`+s
 print s or 0

STDINを介して入力を読み取り、各数値を個別の行に入力して、結果をSTDOUTに出力します。

説明

整数を数字の配列として表す代わりに、各整数をバイナリ表現の「オン」ビットのセットとして表します。つまり、整数nは、nのバイナリ表現で1に等しいビットのインデックスのセットとして表されます。たとえば、10進数の10 10進数は、セット{1、3}として表されます。この表現により、Pythonの集合演算を使用して、算術演算の一部をかなり簡潔に表現できます。

2つのセットを追加するには、(再帰的に)対称差の合計と、それらの交差点に続く整数のセット(集合キャリーに対応するため、最終的に空のセットになり、最終的な合計が得られます) 。)同様に、2つのセットを減算するために、(再帰的に)対称差の差を取得し、後続の整数のセットを(セット)の差(集合借入に対応し、最終的に空のセットになります)この2つの操作の類似性により、これらを1つの関数として実装できます(A)。

乗算(M)は単純な分散加算です。2つのセットABが与えられた場合、前述のように、すべてのセット{ A + b | BB }(ここで、A + Bは集合{ある+のBは | ∈ A })。

整数比較は、2つのセットの辞書式比較になり、降順でソートされます。

ABのD 2つのセットを分割するには、商として空のセットから開始し、B + nがA(単に最大値の差である)以下になるように、最大の整数nを繰り返し見つけますAB、おそらくマイナス1)、追加のn商の要素として、および減算B + NからA上記のようまで、Aは以下となるB、すなわち、それは余りになるまでを。

もちろん、無料のランチはありません。税金は、小数から変換する必要があります。実際、実行時間の大部分を占めるのは10進数への変換です。通常の算術演算の代わりに、上記の演算のみを使用して、「通常の方法」で変換を行います。


好奇心から:s=`sum(2**i for i in d)`+s変換時に組み込みの任意精度演算を利用しませんか?
TheConstructor

1
@TheConstructor No. dは1桁の10進数であるためi、0〜3であり、合計は0〜9です。
Ell16年

4

Java 8、485バイト

機能を命名別の5バイトで減らすことができるdのではなく、divideまたは別の16バイトのクラス定義を数えていない場合。

public class G{int l(String a){return a.length();}String s(String n,String m){while(l(n)>l(m))m=0+m;String a="";for(int c=1,i=l(n);i>0;c=c/10){c=n.charAt(--i)+c-m.charAt(i)+9;a=c%10+a;}return e(a);}String e(String a){return a.replaceAll("^0+(?=[0-9])","");}String divide(String n,String m){String q="",p=q,y;for(int b=0,i=0;b<=l(n);i--){y=n.substring(0,b);if(l(y)==l(p)&&p.compareTo(y)<=0||l(y)>l(p)){y=s(y,p);n=y+n.substring(b);q+=i;b=l(y)+1;i=10;p=m+0;}p=s(p,m);}return e(q)+","+n;}}

次のように使用できます。

public static void main(String[] args) {
    G devision = new G();
    System.out.println(devision.divide("20397882081197443358640281739902897356800000000",
            "265252859812191058636308480000000"));
    System.out.println(devision.divide("31035053229546199656252032972759319953190362094566672920420940313",
            "1234567891011121314151617181920"));
    System.out.println(devision.divide(
            "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
            "247"));
}

降伏

76899763100160,0
25138393324103249083146424239449429,62459510197626865203087816633
1100573825740813795225181252819477770473619155158611722708681386445423816849801159141424129060075102231232666057768175183676764503262931271346408394876267875141461722640873365274628650676808557279259873162169126398101692109801549256156915750794061370041981513180387019893765753438422927286098434193260562682052606153857091520795991080960000000000000000000000000000000000000000000000000,0

ゴルフをしていない:

public class ArbitraryPrecisionDivision {

    /**
     * Length of String
     */
    int l(String a) {
        return a.length();
    }

    /**
     * substract m of n; n >= m
     */
    String s(String n, String m) {
        while (l(n) > l(m))
            m = 0 + m;
        String a = "";
        for (int c = 1, i = l(n); i > 0; c = c / 10) {
            c = n.charAt(--i) + c - m.charAt(i) + 9;
            a = c % 10 + a;
        }
        return e(a);
    }

    /**
     * trim all leading 0s
     */
    String e(String a) {
        return a.replaceAll("^0+(?=[0-9])", "");
    }

    /**
     * divide n by m returning n/m,n%m; m may not start with a 0!
     */
    String divide(String n, String m) {
        // q stores the quotient, p stores m*i, y are the b leading digits of n
        String q = "", p = q, y;
        for (int b = 0, i = 0; b <= l(n); i--) {
            y = n.substring(0, b);
            if (l(y) == l(p) && p.compareTo(y) <= 0 || l(y) > l(p)) {
                y = s(y, p);
                n = y + n.substring(b);
                q += i;
                b = l(y) + 1;
                i = 10;
                p = m + 0;
            }
            p = s(p, m);
        }
        return e(q) + "," + n;
    }

    public static void main(String[] args) {
        ArbitraryPrecisionDivision division = new ArbitraryPrecisionDivision();
        System.out.println(division.divide("20397882081197443358640281739902897356800000000",
                "265252859812191058636308480000000"));
        System.out.println(division.divide("31035053229546199656252032972759319953190362094566672920420940313",
                "1234567891011121314151617181920"));
        System.out.println(division.divide(
                "271841734957981007420619769446411009306983931324177095509044302452019682761900886307931759877838550251114468516268739270368160832305944024022562873534438165159941045492295721222833276717171713647977188671055774220331117951120982666270758190446133158400369433755555593913760141099290463039666313245735358982466993720002701605636609796997120000000000000000000000000000000000000000000000000",
                "247"));
    }
}

配列をm1から9の時間で事前計算せず、のb=0代わりにを開始することで速度を少し犠牲にしましたb=l(m)が、そうすることで多くのバイトを節約しました。任意精度の追加に関心がある場合は、以前のバージョンを参照してください。

これは最短の解決策ではないでしょうが、おそらく良いスタートを切るでしょう。


これに対して加算、乗算、減算も実装する場合、これに500の報奨金を支払います。:DIはStringy精度のアイデアが大好きです。
アディソンクランプ

@VoteToCloseは明日これを見るでしょう。最も難しい部分が完了したと思います。
TheConstructor

1

Mathematica、251バイト

r=Reverse;f=FoldPairList;s={0}~Join~#&;
p[a_,b_]:={First@#,#[[2,1,-1,2]]}/.{Longest[0..],x__}:>{x}&@Reap@f[Sow@{Length@#-1,Last@#}&@NestWhileList[r@f[{#~Mod~10,⌊#/10⌋}&[#+Subtract@@#2]&,0,r@Thread@{#,s@b}]&,Rest@#~Join~{#2},Order[#,s@b]<=0&]&,0s@b,s@a]

説明

10進数の算術は、によって簡単に実装できますFoldPairList。例えば、

times[lint_,m_]:=Reverse@FoldPairList[{#~Mod~10,⌊#/10⌋}&[m #2+#]&,0,Reverse@lint]

単に手で乗算を行うプロセスを模倣します。

times[{1,2,3,4,5},8]
(* {9,8,7,6,0} *)

テストケース

p[{1,2,3,4,5,6,7,8,9},{5,4,3,2,1}] 
(* {{2,2,7,2},{3,9,4,7,7}} *)

を意味し123456789 / 54321= 2272...39477ます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.