Math 如何有效地将数字中的每个数字相乘

Math 如何有效地将数字中的每个数字相乘,math,language-agnostic,Math,Language Agnostic,我想把一个数字中的每个数字相乘 比如说 515 would become 25(i.e 5*1*5) 10 would become 0(i.e 1*0) 111111 would become 1(i.e 1*1*1*1*1*1) 我用这个代码做的 public static int evalulate(int no) { if(no==0)return 0; int temp=1; do { temp=(no%10)*temp;

我想把一个数字中的每个数字相乘

比如说

515 would become 25(i.e 5*1*5)
10 would become 0(i.e 1*0)
111111 would become 1(i.e 1*1*1*1*1*1)
我用这个代码做的

public static int evalulate(int no)
{
    if(no==0)return 0;
    int temp=1;

    do
    {
        temp=(no%10)*temp;
        no=no/10;
    }while(no>0);

    return temp;
}
问题是我想评估大约十亿个像这样的数字

for(int i=0;i<1000000000;i++)evaluate(i);
for(int i=0;i如果可以存储所有数字的每次运算结果,则可以使用。这样,您只需计算1位数字

int prodOf(int num){
   // can be optimized to store 1/10 of the numbers, since the last digit will always be processed
   static std::vector<int> memo(<max number of iterations>, -1); 
   if(num == 0) return 0;

   if(memo[num] != -1 )return memo[num];

   int prod = (num%10)  * prodOf(num/10);

   memo[num] = prod;

   return prod;
}
intprodof(intnum){
//可以优化存储1/10的数字,因为最后一个数字将始终被处理
静态标准::向量备忘录(,-1);
如果(num==0)返回0;
如果(备注[num]!=-1)返回备注[num];
int prod=(数量%10)*prodOf(数量/10);
备注[num]=产品;
返回产品;
}
我做了一些测试, 在我的PC上使用简单的C/C++代码(Xeon 3.2GHz)

最后一个编号=i=9999999==>387420489 nb第23节

#包括“stdafx.h”
#包括
#包括
#未定义跟踪_
内联整数求值(整数编号)
{
#ifdef_跟踪_
std::cout 0);
#ifdef_跟踪_

std::cout首先,计算您可以在内存中存储多少个数字。例如,假设您可以存储999个数字

您的第一步将是预先计算0-999之间所有数字的数字乘积,并将其存储在内存中。因此,您将有一个数组,沿着以下行:

  multLookup = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
                0, 2, 4, 6, 8, 10, 12, 14, 16, 18,
                0, 3, 6, 9, 12, 15, 18, 21, 24, 27,
                0, 4, 8, 12, 16, 20, 24, 28, 32, 36,
                ...]
现在,您可以将数字分解为一组3位数字。例如,如果您的数字是
1739203423
,您可以将其分解为
1
739
203
423
。您可以在
multLookup
数组中查找每一个数字,并将结果相乘,如下所示:

  solution = multLookup[1] * multLookup[739] * multLookup[203] * multLookup[423];
使用这种方法,您的计算速度将提高3倍(因为我们选择了999项存储在内存中)。要提高5倍,请将99999个数字存储在内存中,并遵循相同的步骤。在您的情况下,将其提高5倍意味着您将在29.2秒内得出解决方案

注意:增益与存储在内存中的数字数量并不完全成线性关系。请参阅此答案下注释中的jogojapan的推理,了解其原因

如果您更了解数字的显示顺序或数字的范围(假设您的输入仅在[0,10000]范围内),则可以使此算法更智能

在您的示例中,您正在使用for循环从0迭代到100000000。在这种情况下,这种方法将非常高效,因为内存不会频繁出现页面错误,并且缓存未命中的次数也会更少

但请稍候!您可以更快地执行此操作(针对特定的for循环迭代示例)!!您可以问,如何执行?缓存!假设您正在处理10位数字

假设您从
8934236000
开始。根据内存解决方案中的999位数字,您可以将其分解为
8
934
236
000
。然后您可以乘以:

solution = multLookup[8] * multLookup[934] * multLookup[236] * multLookup[0];
solution = multLookup[8] * multLookup[934] * multLookup[236] * multLookup[1];
接下来,取
8934236001
,将其分解为
8
934
236
,和
001
,然后乘以:

solution = multLookup[8] * multLookup[934] * multLookup[236] * multLookup[0];
solution = multLookup[8] * multLookup[934] * multLookup[236] * multLookup[1];
以此类推……但我们注意到,在接下来的997次迭代中,前三次查找是相同的!因此,我们将其缓存

cache = multLookup[8] * multLookup[934] * multLookup[236];
然后我们使用缓存,如下所示:

for (int i = 0; i < 1000; i++) {
    solution = cache * i;
}
for(int i=0;i<1000;i++){
解决方案=缓存*i;
}

就像那样,我们几乎把时间缩短了4倍。所以你用你得到的29.2秒的解,除以4,在7.3秒内,通过所有十亿个数字,系统地征服目标数字的空间。例如,一旦你做了
12
,计算
121
122
123
等。每个操作只需要一次附加操作。146在技术上是“一些”秒..你考虑过并行化吗?不,@jogojapan建议可能是最快的。如果可能在零上中止,这看起来像是来自Project Euler或其他编程竞赛网站的问题。这是什么原因?1)如果乘以零,你可以提前中止计算,因为在那之后它将永远不会变为非零。2)你可以n跳过保证为零的大范围数字,例如,从900000000跳到911111111,节省11111111次呼叫!您需要小心使用记忆方法,一个包含数亿个元素的数组可能会导致OutOfMemoryException@Patashu我曾经在一个C应用程序中有一百万个条目数组,但从来没有内存不足。@Patashu ya,从未尝试过这种规模。因此我的免责声明。@LuiggiMendoza 10亿比100万大1000倍:)@Patashu您仍然不会添加所有元素相乘的解决方案,否则从一开始就不存储任何结果会更快。我喜欢这种方法,但就时间而言,您估计需要考虑到从内存中获取预先计算的结果(通过数组查找)也需要时间。存储越多,所需时间越长(因为它越来越不适合缓存).说句公道话,我应该更清楚这一点,而不是暗示线性增益。只是尝试了递归。看起来它稍微慢一点,但基本上是相同的速度。很抱歉,我没有看到“公共”静态函数前面的关键字!所以它不是C,而是更像C#…所以忘记OpenMP…最初为四种语言指定的问题。是的,我在这里还是初学者:),你是对的,问题使用的标记很清楚。