Seuraa 
Viestejä950
Liittynyt11.12.2010

Mukava on ollut nähdä, että silloin tällöin palstalla on koodia:

[code:17na6tcr]/*
sqrt_2 fixed-point iteration
5.5.2001 Läskiperse
*/

#include
#include

#define SQRT2_BIT_LENGTH 65536

typedef struct
{
char fix[2*SQRT2_BIT_LENGTH/8];
int bit_kpl;

} fix_point;

fix_point __xx_sqr1, __xx_sqrt1;
fix_point __xx_sqr2, __xx_sqrt2;

fix_point *sqr1=&__xx_sqr1, *sqrt1=&__xx_sqrt1;
fix_point *sqr2=&__xx_sqr2, *sqrt2=&__xx_sqrt2;

void reset_and_init(void)
{
const int ex=sizeof(fix_point);
memset(sqr1, 0, ex); memset(sqrt1, 0, ex);
memset(sqr2, 0, ex); memset(sqrt2, 0, ex);
sqr1->bit_kpl=sqr2->bit_kpl=-1;
}

inline void swap_sqr_ptr(void)
{
fix_point *tmp=sqr1;
sqr1=sqr2; sqr2=tmp;
}

inline void swap_sqrt_ptr(void)
{
fix_point *tmp = sqrt1;
sqrt1=sqrt2; sqrt2=tmp;
}

inline void setBit(char *a, int i)
{
a[i>>3]|=(char)(1<<(i&7));
}

inline void clrBit(char *a, int i)
{
a[i>>3]&=(char)~(1<<(i&7));
}

inline int testBit(char *a, int i)
{
return a[i>>3]&(char)(1<<(i&7))? 1: 0;
}

void sqrt_copy_with_inc(void)
{
int byte_kpl=(sqrt1->bit_kpl>>3)+1;
memcpy(sqrt2->fix, sqrt1->fix, byte_kpl);
sqrt2->bit_kpl=sqrt1->bit_kpl;
setBit(sqrt2->fix, sqrt2->bit_kpl-1);
}

int add(fix_point *C, fix_point *A, fix_point *B)
{
int memory=0, r;
int bit1, bit2;

char *c=C->fix;
char *a=A->fix;
char *b=B->fix;

int i=A->bit_kpl-1;
int j=B->bit_kpl-1;

for (; i>=0; i--, j--)
{
bit1=testBit(a, i);
bit2=j>=0? testBit(b, j): 0;
r=bit1+bit2+memory;
if (r&1) setBit(c, i);
else clrBit(c, i);
memory=r>>1;
}

return memory;
}

int next_iteration_step(void)
{
++sqrt1->bit_kpl;
sqr1->bit_kpl+=2;
sqrt_copy_with_inc();
sqr2->bit_kpl=sqr1->bit_kpl;
if (add(sqr2, sqr1, sqrt1)) return 0;
if (add(sqr2, sqr2, sqrt2)) return 0;
return 1; /* next bit is true, must swap */
}

void main(void)
{
int bit;
reset_and_init();

while (sqrt1->bit_kpl < SQRT2_BIT_LENGTH)
{
if ((bit=next_iteration_step()) != 0)
{
swap_sqr_ptr();
swap_sqrt_ptr();
}

printf("%d", bit);
}
}
[/code:17na6tcr]
Nyt aion jollakin ilveellä vääntää satunnaisgeneraattorin, joka antaa neliöjuuri kahden bittejä, niin kuin tämäkin ohjelma.

Kommentit (4)

Läskiperse
Seuraa 
Viestejä950
Liittynyt11.12.2010

No, eipä koodin räpläämiselle ole paljon sijaa jätetty. Se siitä. Koodi on vain muunnettu helposti käsiteltäväksi olioksi, jossa on yksi funktio, NextBit.

Melko monessa matematiikan ja fysiikan yhteydessä tarvitaan absoluuttisen hyviä satunnaislukuja. piin numeroita käytetään usein, mutta saman asian pitäisi ajaa neliöjuuri kaksi.

[code:3o8odgx2]void main(void)
{
sqrt2_rnd *rnd=new sqrt2_rnd;

for (;;)
{
int bit;
bit=rnd->NextBit();
printf("%d", bit);
}
}
[/code:3o8odgx2]
Ja koko koodina ...

[code:3o8odgx2]
/*
sqrt_2 fixed-point randm
20.3.2013 Läskiperse
*/

#include
#include

class sqrt2_rnd
{
public:

sqrt2_rnd(void);
~sqrt2_rnd(void);
int NextBit(void);

private:

#define SQRT2_BIT_LENGTH (1<<26)

typedef struct
{
char fix[2*SQRT2_BIT_LENGTH/8];
int bit_kpl;

} fix_point;

fix_point __xx_sqr1, __xx_sqrt1;
fix_point __xx_sqr2, __xx_sqrt2;

fix_point *sqr1, *sqrt1;
fix_point *sqr2, *sqrt2;

void reset_and_init(void);
void swap_sqrt_ptr(void);
void swap_sqr_ptr(void);

void sqrt_copy_with_inc(void);
int next_iteration_step(void);

#define FIXP fix_point*
int add(FIXP, FIXP, FIXP);
};

void sqrt2_rnd::reset_and_init(void)
{
const int ex=sizeof(fix_point);
sqr1=&__xx_sqr1; sqrt1=&__xx_sqrt1;
sqr2=&__xx_sqr2, sqrt2=&__xx_sqrt2;
memset(sqr1, 0, ex); memset(sqrt1, 0, ex);
memset(sqr2, 0, ex); memset(sqrt2, 0, ex);
sqr1->bit_kpl=sqr2->bit_kpl=-1;
}

sqrt2_rnd::sqrt2_rnd(void)
{
reset_and_init();
}

sqrt2_rnd::~sqrt2_rnd(void)
{
}

void sqrt2_rnd::swap_sqr_ptr(void)
{
fix_point *tmp=sqr1;
sqr1=sqr2; sqr2=tmp;
}

void sqrt2_rnd::swap_sqrt_ptr(void)
{
fix_point *tmp = sqrt1;
sqrt1=sqrt2; sqrt2=tmp;
}

void setBit(char *a, int i)
{
a[i>>3]|=(char)(1<<(i&7));
}

void clrBit(char *a, int i)
{
a[i>>3]&=(char)~(1<<(i&7));
}

int testBit(char *a, int i)
{
return a[i>>3]&(char)(1<<(i&7))? 1: 0;
}

void sqrt2_rnd::sqrt_copy_with_inc(void)
{
int byte_kpl=(sqrt1->bit_kpl>>3)+1;
memcpy(sqrt2->fix, sqrt1->fix, byte_kpl);
sqrt2->bit_kpl=sqrt1->bit_kpl;
setBit(sqrt2->fix, sqrt2->bit_kpl-1);
}

int sqrt2_rnd::add(fix_point *C, fix_point *A, fix_point *B)
{
int memory=0, r;
int bit1, bit2;

char *c=C->fix;
char *a=A->fix;
char *b=B->fix;

int i=A->bit_kpl-1;
int j=B->bit_kpl-1;

for (; i>=0; i--, j--)
{
bit1=testBit(a, i);
bit2=j>=0? testBit(b, j): 0;
r=bit1+bit2+memory;
if (r&1) setBit(c, i);
else clrBit(c, i);
memory=r>>1;
}

return memory;
}

int sqrt2_rnd::next_iteration_step(void)
{
++sqrt1->bit_kpl;
sqr1->bit_kpl+=2;
sqrt_copy_with_inc();
sqr2->bit_kpl=sqr1->bit_kpl;
if (add(sqr2, sqr1, sqrt1)) return 0;
if (add(sqr2, sqr2, sqrt2)) return 0;
return 1; /* next bit is true, must swap */
}

int sqrt2_rnd::NextBit(void)
{
int bit;
if ((bit=next_iteration_step()) != 0)
{
swap_sqr_ptr();
swap_sqrt_ptr();
}
return bit;
}

void main(void)
{
sqrt2_rnd *rnd=new sqrt2_rnd;

for (;;)
{
int bit;
bit=rnd->NextBit();
printf("%d", bit);
}
}
[/code:3o8odgx2]

Neutroni
Seuraa 
Viestejä30818
Liittynyt16.3.2005

Eikö noissa matemaattisissa vakioissa ole ainakin se vika, että mitä pitemmälle niitä lasketaan sitä enemmän uusien desimaalien laskeminen vie aikaa? Jos satunnaislukuja tarvitaan paljon, se hidastaa ohjelman suoritusta.

Läskiperse
Seuraa 
Viestejä950
Liittynyt11.12.2010

Kyllä. Mutta koodi hidastuu pikkuhiljaa, jos tarvitaan miljoona satunnaislukua. Koko homman perustana oli kauan sitten havainto, että lukujen neliöt voi tuottaa yhteenlaskulla, (kun edellinen neliö tunnetaan):

[code:2t26a9cu]...
16 + 4 + 5 = 25 (=5^2)
25 + 5 + 6 = 36 (=6^2)
36 + 6 + 7 = 49 (=7^2)
49 + 7 + 8 = 64 (=8^2)
...[/code:2t26a9cu]

Suosituimmat

Uusimmat

Uusimmat

Suosituimmat