171021—用do...while和if完成素数完全分解。

此篇填上昨天的坑。
在昨晚之前,对这个问题有一下几点考虑:
1.这不是简单找n的因数,那样的话我们只需要让i递增或递减,遍历一次,和条件的输出就好。这次是要求其所有的质因子,而且按个数输出。这里有两点考虑:

  1. 必须保证是质数,输出2而不能输出4;
  2. 如何让质因子都输出各自该有的个数?即:8 如何输出3个2?

这两个问题可以一同解决,只需设置一个量,去记录每做一次余数为0的除法后的商x,让x而非n去继续参加运算,就可以解决。
考虑需要对满足条件(为n整除)的i做多次相同运算。确定要用循环语句做大结构。
而中间必然存在对i是否满足条件的相关判断。于是,第一版:
这里写图片描述
缺陷多到不能记清了。啥都输不出来。
第二版:一直在输出些乱七八糟的东西
这里写图片描述

第三版:

这里写图片描述
这是昨晚的版本。
显然我们没有考虑到当2不是x的因数时会发生什么。(其实当i不是n的因数时都会发生类似结果而不仅仅是在初始。)
如果初始时i=2不是x的因数。这时候x的值已经不是最初输入的x了。往下走当然不会有好结果。
所以考虑在判断语句if里,当m不等于0时,让else能实现将x的值初始化。而不是保留第一次带余除法完之后留下的商。改动如下:

这里写图片描述
再次引入之前抛弃过的n,让x能一心一意放商的结果。这样,就可以在i不满足条件时将x还原至上一次的值,去取下一个素数。
但还是失败了,输入9,得到了全世界所有的3…
如图所示,在借助草稿纸人工验算后发现,当i=2不符时,程序可跳至3进行判断,但当第一次发现3时因子后,循环依旧执行x=9/3,n永远保持9。也就是说,在发现了一个质因子之后,这个程序会不停重复一模一样的事情。死循环——n没有变化。
于是做了一个我自己都快看不懂的事情:

#include<iostream>
using namespace std;
int main()
{
    int i=2,x,n;
    double m;
    cout<<"输入正整数n="<<endl;
    cin>>n; 
    do
    {
         x=n/i;
         m=n%i;
         if (m==0) 
         {
            cout<<i<<'\t';
            n=x;       //改变n的值,避免死循环。 
          } 
         else
         {
            x=n;
            i++;
         }

    }while(x>1);


 }

在if判断中,如果找到了一个i,输出i之后,把x(n除过一次i的商)给n,让“x=n/i”能够执行针对i的第二次运算。
这次对了。挺爽。

下面是使用C语言实现生成75位的素数的代码: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #include <stdbool.h> #include <gmp.h> // 定义75位的十进制数所需的位数 #define DIGITS 24 // 判断n是否为素数,k为检验次数 bool is_prime(mpz_t n, int k) { // 将n转换为long类型以进行一些初步的判断 long num = mpz_get_ui(n); if (num <= 1) { return false; } if (num == 2 || num == 3) { return true; } if (num % 2 == 0) { return false; } // 将n-1分解为2^r * s的形式 mpz_t r, s; mpz_init(r); mpz_init(s); mpz_sub_ui(s, n, 1); while (mpz_even_p(s)) { mpz_add_ui(r, r, 1); mpz_div_2exp(s, s, 1); } // 进行k次随机检验 gmp_randstate_t rand_state; gmp_randinit_default(rand_state); for (int i = 0; i < k; i++) { // 生成一个随机数a,0<a<n mpz_t a; mpz_init(a); mpz_urandomm(a, rand_state, n); mpz_sub_ui(a, a, 1); if (mpz_cmp_ui(a, 1) < 0) { mpz_add_ui(a, a, 2); } // 计算x = a^s mod n mpz_t x; mpz_init(x); mpz_powm(x, a, s, n); if (mpz_cmp_ui(x, 1) == 0 || mpz_cmp(x, n) == 0) { // 如果x=1或x=n-1,继续检测下一个随机数 mpz_clear(a); mpz_clear(x); continue; } bool found = false; for (int j = 0; j < mpz_get_ui(r) - 1; j++) { // 计算x = x^2 mod n mpz_mul(x, x, x); mpz_mod(x, x, n); if (mpz_cmp_ui(x, 1) == 0) { // 如果x=1,n为合数 found = true; break; } if (mpz_cmp(x, n) == 0) { // 如果x=n-1,继续检测下一个随机数 found = true; break; } } if (!found) { // 如果没有找到x=n-1,n为合数 mpz_clear(a); mpz_clear(x); return false; } mpz_clear(a); mpz_clear(x); } // 如果经过k次检验,n仍然有可能是素数 return true; } int main() { // 初始化随机数生成器 gmp_randstate_t rand_state; gmp_randinit_default(rand_state); // 生成一个75位的随机数 mpz_t n; mpz_init(n); mpz_t max_num; mpz_init(max_num); mpz_ui_pow_ui(max_num, 10, DIGITS); do { mpz_urandomm(n, rand_state, max_num); // 如果生成的数是偶数,则加1变为奇数 if (mpz_even_p(n)) { mpz_add_ui(n, n, 1); } } while (!is_prime(n, 5)); // 输出生成的素数 char str[DIGITS + 2]; mpz_get_str(str, 10, n); printf("%s\n", str); // 释放内存 mpz_clear(n); mpz_clear(max_num); gmp_randclear(rand_state); return 0; } ``` 这个程序使用了GMP库来支持大整数运算,并使用Miller-Rabin素性检验算法来判断随机生成的数是否为素数。同样地,由于素性检验算法存在一定的错误概率,我们在进行检验时需要多次进行,这里使用了5次检验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值