Ohessa 8 bittinen random-funktio, joka etsii pi-ketjuja. Joka kierroksella etsitään myös toistoa.
/******************** * *** Jouni Aro *** * * *** 24.4.2025 *** * ********************/ #include <stdio.h> #include <memory.h> typedef unsigned char uint8; class random { public: random(void); ~random(void); unsigned rnd(unsigned); private: void inc4(void); uint8 tmp8(void); unsigned Z; uint8 R8A, R8B; uint8 avain[256]; int p1, p2, p3, p4; }; random::random(void) { memset(this, 0, sizeof(random)); Z=1+(2<<8)+(3<<16)+(4<<24); p1=1; p2=2; p3=3; p4=4; R8A=101; R8B=202; for (int i=0; i<256; i++) avain[i]=(uint8)i; } random::~random(void) { } inline void random::inc4(void) { ++Z; p1=Z&255; p2=(Z>>8)&255; p3=(Z>>16)&255; p4=(Z>>24)&255; } inline uint8 random::tmp8(void) { R8A+=(uint8)((avain[p1]>>4)^(avain[p2]<<4)); R8B-=(uint8)((avain[p1]<<4)^(avain[p2]>>4)); R8A-=avain[p3]&(uint8)255; R8B+=avain[p4]&(uint8)255; inc4(); return R8A^R8B; } inline void swap(uint8 &x, uint8 &y) { register uint8 z=x; x=y; y=z; } inline unsigned random::rnd(unsigned max) { register unsigned x=tmp8(); register unsigned y=tmp8(); swap(avain[x], avain[y]); return tmp8()%max; } /* main-funktio tutkii, kuinka pitkiä pi-ketjuja löytyy, samalla etsitään, koska toisto alkaa. toistaako-funktio etsii rnd-syklistä toistoa. */ int toistaako(random &F0, random &F, double &loop) { char *A=(char*)&F0; char *B=(char*)&F; int size=sizeof(random); for (int i=0; i<size; i++) if (A[i]!=B[i]) return 0; for (unsigned k=0x01; k!=0; k++) printf("toistaa %0.0f\n", loop); return 1; } int main(void) { char *pi="1415926535897932384626433832795028841971693993751058209749445923"; unsigned maxKpl=0, i=0; double loop=0.00; random F0, F; for (;; loop+=1.0) { int x=F.rnd(10)+(int)'0'; if ((char)x==*(pi+i)) { ++i; } else { if (i>maxKpl) { maxKpl=i; printf("pi %d numeron tarkkuudella\n", maxKpl); printf("loop=%0.0f\n\n", loop); i=0; } else i=0; } if (toistaako(F0, F, loop)) break; } return 1; }
Ohjelma tulostaa pi-ketjuja, ja tulos näyttää tältä:
pi 1 numeron tarkkuudella loop=16 pi 2 numeron tarkkuudella loop=24 pi 3 numeron tarkkuudella loop=2128 pi 4 numeron tarkkuudella loop=17743 pi 5 numeron tarkkuudella loop=52605 pi 6 numeron tarkkuudella loop=1296831 pi 8 numeron tarkkuudella loop=22506900 pi 9 numeron tarkkuudella loop=5882993429 pi 10 numeron tarkkuudella loop=15768925109 pi 11 numeron tarkkuudella loop=47846462953 pi 12 numeron tarkkuudella loop=1749902211599 jne...
Minulla on tällainen random-olio. Voitko analysoida, kumpi näistä on parempi? Tämäkin testi etsii piin desimaaleja. Silmukan näkee siitä, että toistuu täsmälleen sama tulos ja tulosta edeltävä puskuri.
#include <stdio.h> #include <stdint.h> #include <string.h> #include <ctype.h> template <typename UINT, int POW> struct prandom { static_assert(POW > 0, "SIZE must be greater than 0"); static_assert(POW <= 32, "SIZE must be less than or equal to 32"); typedef UINT uint_type; const int size = 1 << POW; const uint_type mask = (1 << POW) - 1; UINT state[1 << POW]; int index; prandom(uint64_t seed = 0) : index(0) { for (int i = 0; i < size; ++i) { state[i] = i + (seed >> (i * (sizeof(uint_type) * 8))); } } uint_type next() { uint_type a = state[index] + 1; index = (index + 1) & mask; uint_type b = state[index]; state[index] = (b << 4) ^ (b >> 4) ^ (a << 3) ^ (a >> 3); return state[index]; } }; typedef prandom<uint8_t, 8> p8rng_t; void pi_test() { const char pi[] = "1415926535897932384626433832795028841971693993751058209749445923"; const int buf_size = strlen(pi); char buf[buf_size + 1] = {0}; int found_max = 0, found_now = 0; uintmax_t i = 0; p8rng_t rng; while (pi[found_max] != '\0') { ++i; uint8_t r = (rng.next() % 10) + '0'; const int buf_i = i % buf_size; buf[buf_i] = r; if (r == pi[found_now]) { found_now++; if (found_now >= found_max) { found_max = found_now; printf("Found %d digits of pi ending at [%ju]\n", found_max, i); for (int j = 0; j < buf_size; ++j) { if (!isprint(buf[j])) { buf[j] = '.'; } } printf("last %d values: %.*s%.*s\n", buf_size, buf_size - buf_i - 1, buf + buf_i + 1, buf_i + 1, buf); } } else { found_now = 0; } } } int main() { pi_test(); return 0; }