kaeru

気になったことをつらつらと書きます

Cアルゴリズム エラトステネスの篩

2009年02月27日 | Weblog
学校の課題の関係上出力等を提出用にいじっています。前回のビット回転同様にプログラムには無駄が多くわかりづらい考え方をしているかもしれませんが参考にどうぞ。一応わかるようにコメント、インデントをつけていますがわかりづらいかもしれません。

#include <stdio.h>

#define N 100000
#define tn 1471821271

main()
{
    int i,j,ans = 0,n = 0,nc = 0;
    //n:出力数をカウント nc:素数のカウント ans:素因数分解の要素数
    int sosur[N] = {0,0};
    //2~100,000の数を記憶 配列0,1番目は初期値を0とする
    int sosuw[N]; //素数を出力する配列
    int bun[100];     //素因数分解で出た素数を格納
    void sosu(int sosur[N], int sosuw[N], int dn, int *nc);
    //エラトステネスの篩
    void soinsu(int sosuw[N], int bun[100], int sn, int nc, int *b);
    //素因数分解を計算 sn:素因数分解する数

    sosu(sosur, sosuw, N, &nc); //エラトステネスの篩

    //出力処理
    for(j = 1 ; j <= 30; j++){ //出力配列の最初1行10個とし3行出力
        printf("%6d",sosuw[j-1]);
        if((j % 10) == 0){ //出力した素数が10個のとき改行
            printf("\n");
        }
    }
    printf("\n");

    n = 1;
    i = nc - (nc / 10) * 10; //素数の総数の1の位を取り出す
    if(i==0){ //1の位が0のとき
        i = 10;
    }
    for(j = (nc - (20+i)) ; j <nc; j++){//出力配列の最後の3行を出力         if(n == 10){ //出力した素数が10個のとき改行
            printf("\n");
            n = 0;
        }
        n += 1; //出力した素数をカウント
    }

    printf("\n");
    printf("count:%d\n\n", nc); //素数の個数を出力

    soinsu(sosuw, bun, tn, nc, &ans); //素因数分解を計算
    printf("素因数分解:1471821271\n");
    if(ans == 0){
         printf("素因数分解できませんでした");
    }
    else{
         for(i = 0; i <ans; i++){ //素因数分解の結果出力          }
    }

}

void sosu(int sosur[N], int sosuw[N], int dn, int *nc){
//エラトステネスの篩
    int i,j;

    for(i = 2; i <= N; i++){ //2~100,000を配列に格納
         sosur[i] = i;
    }

    for(i = 2; (i*i) <= N ; i++){ //エラトステネスの篩
         if(sosur[i] != 0){ //配列のi番目が0のとき何もしない
             for(j = 2*i; j <N; j+=i){                sosur[j] = 0;
             }
         }
    }

    for(i = 0; i <N; i++){//配列に格納されている素数を出力配列に入れる             sosuw[*nc] = sosur[i];
            *nc += 1; //素数をカウント
         }
    }
}

void soinsu(int sosuw[N], int bun[100], int sn, int nc, int *b){
 //素因数分解
    int i = 0,j = 0,w,m; //m:snを割る数(素数)
    int temp; //mで割られた数

    temp = tn;
    while(temp != 1){ //割られて1とならない間繰り返す
        m = sosuw[i]; //出力配列の素数をmに代入
        if((temp % m) == 0){ //割り切れたとき
            temp = temp / m;
            bun[j] = m; //素因数分解の要素を格納
            j += 1;
            i = 0;
        }
        if(nc == i){
            j = 0;
            break;
        }
        i += 1;
    }
}

Cアルゴリズム ビット回転

2009年02月25日 | Weblog

入力された16進数を2進数に変換しシフト量分回転させるプログラムです。
コメントやインデントの関係上読みにくいかもしれませんが参考にどうぞ
includeの<>←はブログで表示されてなかったようなので大文字にしましたコンパイルをするときは小文字に直してください。

#include <stdio.h>
#include <string.h>
#define N 32
static unsigned int f[32] =
{ 0x00000001, 0x00000002, 0x00000004, 0x00000008,
0x00000010, 0x00000020, 0x00000040, 0x00000080,
0x00000100, 0x00000200, 0x00000400, 0x00000800,
0x00001000, 0x00002000, 0x00004000, 0x00008000,
0x00010000, 0x00020000, 0x00040000, 0x00080000,
0x00100000, 0x00200000, 0x00400000, 0x00800000,
0x01000000, 0x02000000, 0x04000000, 0x08000000,
0x10000000, 0x20000000, 0x40000000, 0x80000000 };

main(){
unsigned int e,er,el;
//e:入力した16進数 er:右にシフトした16進数 el:左にシフトした16進数
unsigned int s; //s:シフトする量
void prbit(unsigned int ); //16進数を2進数のビット列に変換出力
void lshift( unsigned int s, unsigned int e, unsigned int *el);
    //左シフト回転
void rshift( unsigned int s, unsigned int e, unsigned int *er);
//右シフト回転

printf("16進数を入力せよn");
scanf("%x",&e); //16進数の入力

printf("ビット表示 ");
prbit(e); //ビット列に変換出力

printf("nビットシフト量を入力せよn");
scanf("%d",&s); //シフト量の変換

lshift(s,e,&el); //左シフト回転
printf("%d-ビット左回転",s);
prbit(el); //回転したビット列を出力

rshift(s,e,&er); //右シフト回転
printf("n%d-ビット右回転",s);
prbit(er); //回転したビット列の出力

}

void prbit(unsigned int e){ //ビット出力
int i,bit;

for(i = 0; i <N; i++){         //入力データとiビットのみが1のデータとのビット積
bit = 1;  //1ならば出力用に1を代入
else
bit = 0;  //0ならば出力用に0を代入
if((i % 4) == 0) //ビット列を4つずつ区切る
printf(" ");

printf("%d",bit);
}
}

void lshift( unsigned int s, unsigned int e, unsigned int *el){
unsigned int er;

*el = e << s; //左にsシフト
er = e >> (N-s); //あふれるビット列を末尾に持ってくる
*el |= er;  //左シフトとあふれたビット列のビット和をとる
/*左シフト回転の動作
例)入力 1111ffff
ビット表示 e: 0001 0001 0001 0001 1111 1111 1111 1111
3ビット左シフト er: 1000 1000 1000 1111 1111 1111 1111 1000
あふれるビットを末尾に持ってくる(32-3 = 29ビット右シフト)
*el: 0000 0000 0000 0000 0000 0000 0000 1000
*el | er: 1000 1000 1000 1111 1111 1111 1111 1000
*/
}

void rshift( unsigned int s, unsigned int e, unsigned int *er){
//右シフト回転
unsigned int el;

*er = e >> s; //右にsシフト
el = e << (N-s); //あふれるビット列を先頭に持ってくる
*er |= el;  //右シフトとあふれたビット列のビット和をとる

/*右シフト回転の動作
例)入力 1111ffff
ビット表示  e: 0001 0001 0001 0001 1111 1111 1111 1111
3ビット右シフト*er: 0000 0010 0010 0010 0011 1111 1111 1111
あふれるビットを先頭に持ってくる(32-3 = 29ビット左シフト)
el: 1110 0000 0000 0000 0000 0000 0000 0000
     *er | el: 1110 0010 0010 0010 0011 1111 1111 1111
*/
}