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, "POW must be greater than 0");
static_assert(POW <= 32, "POW 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;
}Aihe on jo aika vanha, joten et voi enää vastata siihen.