代码之家  ›  专栏  ›  技术社区  ›  78282219

SAS中的主因子分解循环

  •  0
  • 78282219  · 技术社区  · 6 年前

    我正在做一些小任务来提高我的编码和效率,今天我要解决的问题来自于ProjectEuler,问题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 回复  |  直到 6 年前
        1
  •  2
  •   Richard    6 年前

    你需要一些内部循环来移除每个因素的所有力量。

    因子检验的几个问题

    • 移除2的幂只移除因子分解中2的第一个可能的多个幂。
    • 同样的 do i 循环(实际上是 factor )中。
    • 这个 我做 按1迭代,这意味着您正在检查偶数。在排除2个因素后,无需执行此操作-- do i=3 to a by 2 … 会更好的
      • 素数因子的上限是sqrt(number)
      • 如果不想计算sqrt,可以使用/2
      • 不管 to 当数字减少到1时,你将退出分解循环。 to a 可以。
      • 一个更聪明的“解算器”将跟踪动态已知的素数并只测试那些素数。如果在检查最后一个已知的素数之后没有实现完全分解,则必须前进2

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

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

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

    • do … while(condition); …iterated-statements… end;
      • 0个或多个循环-在执行任何迭代语句之前完成条件测试
    • do … until(condition); … end;
      • 一个或多个循环-在执行迭代语句后执行条件测试
    • do index=from-value to to-value by by-value; … end;
      • 索引按相等的步骤变化,可以用作迭代语句的一部分
      • to值只计算一次,不能由迭代语句更改
      • while until 可以固定在 do index= 陈述
      • to value是可选的,但是将无休止地循环,除非 虽然 直到 存在,或者至少有一个迭代语句执行 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的“语言调查”中,我会尝试用正在学习的新语言编写上面的代码。