SAS中的主要分解循环

时间:2018-07-11 07:14:15

标签: loops if-statement sas do-loops sas-studio

我正在做一些小任务来提高编码和效率,我今天正在处理的问题是来自项目Euler,问题3:

“找到600851475143的最大质数”

我写的代码是:

data test;

a = 600851475143;
/*The subsequent a's are the next parts of the loop I'm trying to incorporate*/
/*a = 8462696833;*/
/*a = 10086647;*/
/*a = 6857;*/

if mod(a,2) = 0 then do;

a = a / 2;

end;

else do;

    do i = 3 to a until(flag);

        if mod(a,i) = 0 and i < a then do;

            b = i ;
            a = a / b ;
            flag = 1;
            output;

        end;
    end;

end;

run;

如何使变量成为一个循环并变小然后在没有更多a的情况下终止,即由于没有因式分解,最后一次迭代不会产生数据集。

我也很高兴收到有关如何使此代码更高效的任何提示,因为我正在尝试学习

1 个答案:

答案 0 :(得分:2)

您将需要一些内部循环来消除每个因素的所有功效。

因素检查的一些问题

  • 2的幂仅可除去因式分解中2的许多幂中的第一个。
  • do i循环(实际上是factor)也是如此。
  • do i以1进行迭代,这意味着您正在检查偶数。删除2个因素后无需执行此操作-do i=3 to a by 2 …会更好
    • 数字素因数的上限是sqrt(number)
    • 如果您不想计算sqrt,则可以使用number / 2
    • 无论to为何,当数字减少为1时,您都将退出因式分解循环,因此to a没问题。
    • 更聪明的“求解器”将动态跟踪已知的质数,并仅对其进行测试。如果在检查完最后一个已知素数后仍未实现完全分解,则必须提前2

使用与解决方案中的角色相对应的变量名是有意义的-因此,考虑使用i而不是factor。当然,对于个人代码,您可以使用所需的名称,但是对于将来由您或其他人维护的代码,最佳做法是使用好的变量名。

在SAS中,不要在DTA步骤的顶部硬编码单个测试值,而应考虑处理(素数分解)数据集中包含的任意数量的数字。

SAS中的循环是通过各种do代码构造

  • do … while(condition); …iterated-statements… end;
    • 0个或多个循环-在执行任何迭代语句之前先进行条件测试
  • do … until(condition); … end;
    • 1个或更多循环-执行迭代语句后进行条件测试
  • do index=from-value to to-value by by-value; … end;
    • 索引以相同的步长变化,可以用作迭代语句的一部分
    • to-value仅计算一次,并且不能由迭代语句更改
    • whileuntil可以添加到do index=语句上
    • to-value是可选的,但是除非存在whileuntil,或者至少一个迭代语句执行leave语句,否则

您选择哪种取决于问题。

制作一组要处理的数字数据

data numbers; input number; format number 16.; datalines;
64
720
30
600851475143
8462696833
10086647
6857
run;

示例代码

内部循环用于消除出现多次的因素。

已更改:使用内-内循环(= -1,1)施加6n +/- 1可能是选择可能因素的主要定理。

data prime_factorizations(keep=number factor power);

  set numbers;
  objective = floor(abs(number));

  factor = 2;
  do power = 0 by 1 while (mod(objective,factor) = 0);
    objective = objective / factor;
  end;
  if power then output;

  factor = 3;
  do power = 0 by 1 while (mod(objective,factor) = 0);
    objective = objective / factor;
  end;
  if power then output;

  * after 2 and 3 all primes are of form 6n +/- 1;
  * however, not all 6n +/- 1 are prime;

  * in essence operate a sieve to check for factors;
  * of course the best sieve is a list of primes,
  * but 6n +/- 1 knocks out a lot of unnecessary checks; 

  do n = 1 to objective while (objective > 1);
    do offset = -1, 1;
      factor = 6*n + offset;
      do power = 0 by 1 while (mod(objective,factor) = 0);
        objective = objective / factor;
      end;
      if power then OUTPUT;
      if objective = 1 then leave;
    end;
  end;
run;

title "Prime factorization of some numbers";
proc print noobs data=prime_factorizations;
run;

proc sql;
  title "Max prime factor of various numbers";
  select number, max(factor) as max_prime_factor
  from prime_factorizations group by number;
quit;

title;

当然,这不是实际的大质数搜寻器的工作方式,而是对使用任何给定语言进行编程的很好的介绍。回到CS“语言调查”,我将尝试使用正在学习的新语言对上述代码进行编码。