用长整数除长字符串

时间:2014-09-09 03:12:40

标签: c++ algorithm

我想划分一个只包含长整数的长字符串。所以我尝试这样做:

string divide(string s,long long num)
{
bool flag=true; 
while(flag)
{
    string result="";
    flag=false;
    long long int length=s.size();
    long long int d=0,j=-1;
    for(long long int i=0;i<length;i++)
    {
        d*=10;
        d+=s[i]-48;
        if(j==-1 && d/num!=0)
            j=i;
        result+=(char)(d/num + 48);
        d%=num;
    }

    if(d==0)
    {
        s="";
        for(long long int i=j;i<length;i++)
            s+=result[i];
        factors.push_back(num);
        flag=true;
    }
 }
 return s;
} 

但是我觉得大字符串的速度很慢。所以用任何更快的方法来划分长整数字符串。

另外,请帮助我以更好的方式实现模数操作。

2 个答案:

答案 0 :(得分:1)

for(long long int i=0;i<length;i++)
{
    d*=10;
    d+=s[i]-48;
    if(j==-1 && d/num!=0)
        j=i;
    result+=(char)(d/num + 48);
    d%=num;
}

你在这里计算d/num两次,这很浪费,但我会忘记完全记住这个循环中的j值,并且只是为了速度最大化它。您还应该将result作为数组而不是字符串累积,而不是将long long用于数组索引或循环计数器:

char result[1000]; // or whatever your upper limit is
for (int i = 0; i < length; i++)
{
    d = d*10+s[i]-'0';
    result[i] = (char)(d/num + '0');
    d %= num;
}

然后在完成后跳过前导零。根据输入的生成方式,在开始循环之前跳过被除数中的前导零值也是值得的。

注意,如果d != 0结尾,您的代码无法正常运行。如果有余数,则返回被除数而不是商。如果你正在分解这可能是好的,但对于年轻球员来说这是一个陷阱。

答案 1 :(得分:0)

我在这里使用unsigned long long,消除了符号位的不必要的混乱。

如果你的无符号长多头可以管理最多10 ^ n的数字,那么如果你的除数是&gt;则该除法将不起作用。 10 ^(N-1)。但这对你来说可能不是问题。

假设64位无符号长long,我们最多可以处理10 ^ 19。在您读取19位数(在任何前导零之后)之后,不需要进行任何分割,然后您可以继续,为每个分区收集结果的多个数字 - 其中该数字取决于除数的大小

所以,假设我们有一个除数,10 ^ 11&lt; divisor&lt; = 10 ^ 12,我们最多可以处理10 ^ 19,然后:

  1. 读取19位数(跳过前导零),然后除以:这将是 生成结果的前8位或9位数和初始值 其余部分。

    第一步类似于步骤3和4,除了:(a)显然不需要在结果中添加前导零,并且(b)第一个分区可能产生9位数的结果,其中保证分裂产生8.(因为在随后的分裂中,我们正在处理迄今为止的余数,这必然是&lt; divisor * 10 ^ 8.)

  2. 读取被除数的另外8位数(将余数乘以10 ^ 8并加上这些数字)。

  3. 当剩余部分小于10 ^ 18时,读取被除数的更多数字 - 为结果的每个更多数字添加零。

  4. 除以生成答案的后8位数字并更新余数。

  5. 返回第2步。

  6. 显然,当你用完数字时,你需要进行最后的除法,给出结果的最后数字(取决于1到7位数)。但这是一个SMOP。

  7. 注意:考虑到%的速度有多慢,您可以通过乘法和减法来替换它 - 尽管您的编译器可能会为您执行此操作。 (可悲的是,我在标准中找不到ulldiv()。)

    如果你的除数很小(对于无符号的长整数),这将一次生成许多数字的结果。如果它很大,那么也许只有一两个。我不知道是否值得收集两个未签名的长期股息并进行双字除法......但如果输入数字非常非常长,那么一次收集18位或更多位数的答案看起来诱惑我!