Opis wybranych bibliotek standardowych
Transkrypt
Opis wybranych bibliotek standardowych
UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "stdlib.h" – wybrane funkcje void exit( int status ); - przerywa działanie programu opróŜnia wszystkie bufory i zwraca kod do systemu operacyjnego – status int atoi( const char *string ); - konwertuje łańcuch na liczbę całkowitą typu int long atol( const char *string ); - konwertuje łańcuch na liczbę całkowitą typu long int float atof( const char *string ); - konwertuje łańcuch na liczbę zmiennoprzecinkową typu float char *itoa( int value, char *string, int radix ); - konwertuje liczbę całkowitą typu int na łańcuch znaków value - liczba konwertowan string - wskaźnik na łańcuch (max długość 33 znaki) radix - podstawa systemu przeliczania char *fcvt( float value, int count, int *dec, int *sign ); - konwertuje liczbę zmiennoprzecinkową typu float na łańcuch znaków zwracając wskaźnik na statycznie zaalokowany bufor, kolejne wywołanie funkcji niszczy poprzednio otrzymany rezultat value - liczba konwertowaną count - liczba cyfr po przecinku dec - wskaźnik gdzie zwracana jest pozycja kropki względem początku łańcucha sign - wskaźnik gdzie zwracana jest pozycja znaku względem początku łańcucha int toupper( int c ); - przekształca literę w jej duŜy odpowiednik int tolower( int c ); - przekształca literę w jej mały odpowiednik int abs( int n ); - wartość bezwzględna long labs( long n ); - wartość bezwzględna dla liczb long int int rand( void ); - generuje wartość losową z przedziału (0,RAND_MAX) void srand( unsigned int seed ); - inicjalizuje generator liczb losowych wartością seed 1 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "stdlib.h" – wybrane funkcje, c.d. void *malloc( size_t size ); - alokuje pamięć o rozmiarze size bajtów i zwraca wskaźnik na początek zaalokowanego obszaru void *calloc( size_t num, size_t size ); - alokuje pamięć na num elementów o rozmiarze size bajtów i zwraca wskaźnik na początek zaalokowanego obszaru. Zeruje zaalokowany obszar pamięci void free( void *memblock ); - zwalnia zaalokowany obszar pamięci 2 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "string.h" – wybrane funkcje int sprintf( char *buffer, const char *format [, argument] ... ); - działa analogicznie do printf zapisując sformatowany łańcuch do łańcucha buffer. Zwraca wartość zawiera liczbę zapisanych znaków char *strcat( char *strDestination, const char *strSource ); - dodaje łańcuch strSource do strDestination. Zwracana wartość: wskaźnik do łańcucha do którego dołączany jest tekst char *strncat( char *strDest, const char *strSource, size_t count ); - analogicznie jak strcat lecz kopiuje nie więcej niŜ count znaków char *strchr( const char *string, int c ); - wyszukuje pierwsze wystąpienie znaku c w łańcuchu string . Zwracana wartość: wskaźnik na znaleziony znak bądź NULL jeśli nie znaleziony char *strrchr( const char *string, int c ); - analogicznie jak strstr lecz od końca int strcmp( const char *string1, const char *string2 ); - porównanie dwóch łańcuchów. Zwracane wartośći: < 0 - string1 mniejszy niŜ string2 = 0 - string1 i string2 identyczne > 0 - string1 większy niŜ string2 int strncmp( const char *string1, const char *string2, size_t count ); - analogicznie jak strcmp lecz nie więcej niŜ count znaków char *strcpy( char *strDestination, const char *strSource ); - kopijuje łańcuch strDestination do strSource usuwając poprzednią wrtość strDestination. Zwracana wartość: wskaźnik do łańcucha do którego kopiowany jest tekst char *strncpy( char *strDest, const char *strSource, size_t count ); - analogicznie jak strcpy lecznie więcej jak count znaków size_t strlen( const char *string ); - zwraca długość łańcucha string char *strlwr( char *string ); - przekształca wszystkie duŜe litery łańcucha string na małe char *_strupr( char *string ); - przekształca wszystkie małe litery łańcucha string na duŜe char *strpbrk( const char *string, const char *strCharSet ); - wyszukuje pierwszego wystąpienia jednego ze znaków z łańcucha strCharSet w łańcuchu string 3 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "math.h" – wybrane funkcje float acos( float x ); - oblicza arccos(x) float asin( float x ); - oblicza arcsin(x) float atan( float x ); - oblicza arctg(x) float atan2( float x , float y ); - oblicza arctg(x/y) float ceil( float x ); - oblicza najmniejszą liczbę całkowitą większą lub równą x float floor( float x ); - oblicza największą liczbę całkowitą mniejszą lub równą x float cos( float x ); - oblicza cos(x) float cosh( float x ); - oblicza hiperboliczny cos(x) float exp( float x ); - oblicza ex float fabs( float x ); - oblicza wartośc bezwględną float log( float x ); - oblicza logarytm naturalny ln(x) float log10( float x ); - oblicza logarytm dziesiętny log(x) float pow( float x, float y ); - oblicza xy float sin( float x ); - oblicza sin(x) float sinh( float x ); - oblicza hiperboliczny sin(x) float sqrt( float x ); - oblicza pierwiatek kwadratowy z x float tan( float x ); - oblicza tg(x) float tanh( float x ); - oblicza hiperboliczny tg(x) 4 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "stdio.h" – wybrane funkcje char *gets( char *buffer ); - wczytuje linie z urządzenia wejściowego int printf( const char *format [, argument]... ); - drukuje sformatowany tekst na urządzeniu wyjściowym int putchar( int c ); - wysyła znak c na urządzenie wyjściowe int puts( const char *string ); - wysyła łańcuch string na urządzenie wyjściowe int scanf( const char *format [,argument]... ); - wczytuje sformatowany tekst z urządzenia wejściowego FILE *fopen( const char *filename, const char *mode ); - otwiera plik o nazwie filename w trybie wyszczególnionym w mode. Wartość zwracana: wskaźnik na otwarty plik lub NULL gdy nie udało się otworzyc pliku. Domyślnie plik otwierany w trybie tekstowym. mode – łańcuch opisujący tryb otwarcia pliku: "r" - plik otwierany do odczytu. Jeśli plik istnieje funkcja zwraca błąd "w" - pusty plik otwierany to zapisu. Jeśli plik istnieje jego zawartość jest kasowana "a" - plik otwierany w trybie "dołączania". Jeśli plik istnieje znacznik pliku ustawiany na końcu, w przeciwnym razie plik jest tworzony i znacznik ustawiany na początku "r+" - plik otwierany w trybie odczytu i zapisu. Plik musi istnieć "w+" - pusty plik otwierany w trybie odczytu i zapisu. Jeśli plik istnieje jego zawartość jest kasowana "a+" - plik otwierany w trybie "dołączania" i czytania. Jeśli plik istnieje znacznik pliku ustawiany na końcu, w przeciwnym razie plik jest tworzony i znacznik ustawiany na początku "t" - plik otwierany w trybie tekstowym "b" - plik otwierany w trybie binarnym int fclose( FILE *stream ); - zamyka plik. stream : wskaźnik na plik. Wartość zwracana: 0 – gdy zamknięcie się powidło, EOF w przeciwnym wypadku int feof( FILE *stream ); - sprawdza czy znacznik znajduje się na końcu pliku. Wart. zwr. 1 – tak, 0 – nie 5 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Biblioteka "stdio.h" – wybrane funkcje, c.d. int fseek( FILE *stream, long offset, int origin ); - przenosi znacznik pliku w określone miejsce. Wart. zwr.: 0 – gdy się powiodło, <>0 – w przeciwnym razie. Znacznik przesuwany jest do pozycji origin względem pozycji offset, która moŜe przyjmować wartości: SEEK_CUR – obecna pozycja znacznika pliku SEEK_END – koniec pliku SEEK_SET – początek pliku long ftell( FILE *stream ); - zwraca obecną pozycję znacznika pliku char *fgets( char *string, int n, FILE *stream ); - czyta jedną linię pliku (do napotkania znaku końca lini -\n), lub wczytania n-1 znaków. Wart. zwr.: wskaŜnik na łańcuch lub NULL w przypadku błędu int fputs( const char *string, FILE *stream ); - zapisuje łańcuch do pliku. Wart. zwr. EOF gdy błąd int fgetc( FILE *stream ); - czyta jeden znak z pliku. Wart. zwr.: kod znaku lub EOF gdy osiągnięto koniec pliku int fputc( int c, FILE *stream ); - zapisuje znak do pliku. Wart. zwr. EOF gdy błąd int fprintf( FILE *stream, const char *format [, argument ]...); - zapisuje do pliku sformatowany tekst. Wart. zwr.: ilość znaków zapisanych do pliku lub wartość<0 gsy błąd int fscanf( FILE *stream, const char *format [, argument ]... ); - wczytuje sformatowany tekst z pliku. Wart. zwr.: ilość przeczytanych pól, 0 – gdy Ŝadne pole nie zostało przeczytane, EOF gdy błąd lub koniec pliku int fflush( FILE *stream ); - opróŜnia bufory pliku. Wart. zwr.: 0 – operacja powidła się, EOF – błąd size_t fread( void *buffer, size_t size, size_t count, FILE *stream ); - czyta z pliku niesformatowane dane do bufora buffer. Ilość danych: count o rozmiarze size. Wart. zwr.: ilość przeczytanych elementów size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream ); - zapisuje do pliku niesformatowane dane z bufora buffer. Ilość danych: count o rozmiarze size. Wart. zwr.: ilość zapisanych elementów 6 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 1. Przeliczanie °C na °F, wersja 1 #include <stdio.h> main() { int lower, upper, step; float fahr, celsius; lower=0; upper=300; step=20; fahr=lower; while(fahr<=upper) { celsius=(5.0/9.0)*(fahr-32.0); printf("%4.0f %6.1f\n", fahr, celsius); fahr+=step; } } Przykład 2. Przeliczanie °C na °F, wersja 2 #include <stdio.h> main() { int fahr; for(fahr=0;fahr<=300;fahr+=20) printf("%4d %6.1f\n", fahr, (5.0/9.0)*(fahr-32.0)); } Przykład 3. Zliczanie liczby znaków wprowadzonych z klawiatury, wersja 1 #include <stdio.h> main() { long nc; } nc=0; while(getchar()!=EOF) ++nc; printf("%ld\n",nc); Przykład 4. Zliczanie liczby znaków wprowadzonych z klawiatury, wersja 2 #include <stdio.h> main() { double nc; } for (nc=0;getchar()!=EOF;nc++) ; printf("%.0f\n",nc); 7 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 5. Zliczanie liczby wierszy #include <stdio.h> main() { int c,nl; nl=0; while((c=getchar())!=EOF) if (c=='\n') ++nl; printf("%d\n",nl); } Przykład 6. Zliczanie liczby znaków, słów i linii #include <stdio.h> #define YES #define NO 1 0 main() { int c,nl,nw,nc,inword; } inword=NO; nl=nw=nc=0; while((c=getchar())!=EOF) { nc++; if (c=='\n') nl++; if (c==' ' || c=='\n' || c=='\t') inword=NO; else if (inword==NO) { inword=YES; nw++; } } printf("%d %d %d\n",nl,nw,nc); 8 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 7. Zliczanie liczby wystąpień białych znaków, cyfr i pozostałych #include <stdio.h> main() { int c,i,nwhite,nother; int ndigit[10]; nwhite=nother=0; for(i=0;i<10;i++) ndigit[i]=0; while((c=getchar())!=EOF) if(c>='0' && c<='9') ndigit[c-'0']++; else if(c==' ' || c=='\n' || c=='\t') nwhite++; else nother++; } printf("Cyfry="); for(i=0;i<10;i++) printf(" %d",ndigit[i]); printf("\nBiale znaki = %d, inne = %d\n",nwhite,nother); Przykład 8. Zliczanie liczby znaków w pliku tekstowym #include <stdio.h> main() { FILE *PlikWe; long nc; } nc=0; if ((PlikWe=fopen("test.txt","rt"))!=NULL) { while(fgetc(PlikWe)!=EOF) ++nc; fclose(PlikWe); printf("%ld\n",nc); } else printf("Nie mozna otworzyc pliku\n"); 9 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 9. #include <stdio.h> main() { FILE *PlikWe; int c,nl; nl=0; if ((PlikWe=fopen("test.txt","rt"))!=NULL) { while((c=fgetc(PlikWe))!=EOF) if (c=='\n') ++nl; fclose(PlikWe); printf("%d\n",nl); } else printf("Nie mozna otworzyc pliku\n"); } Przykład 10. #include <stdio.h> enum InWordType { YES, NO }; main() { FILE *PlikWe; int c,nl,nw,nc; enum InWordType inword; inword=NO; nl=nw=nc=0; } if ((PlikWe=fopen("test.txt","rt"))!=NULL) { while((c=fgetc(PlikWe))!=EOF) { nc++; if (c=='\n') nl++; if (c==' ' || c=='\n' || c=='\t') inword=NO; else if (inword==NO) { inword=YES; nw++; } } printf("%d %d %d\n",nl,nw,nc); fclose(PlikWe); } else printf("Nie mozna otworzyc pliku\n"); 10 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 11. Metoda sortowania przez wstawianie proste Algorytm NaleŜy wykonać następujące kroki aby posortować tablicę, 1. Ustaw i na 0 2. Ustaw j na (i + 1) 3. JeŜeli a[i] > a[j], zamięn ich wartości 4. Ustaw j na (j + 1). Jeśli j < n idź do kroku 3 5. Ustaw i na (i + 1). JeŜeli i < (n – 1) Idź do kroku 2 6. tablica a jest posortowana w kolejności rosnącej. Uwaga : a jest tablicą zawierającą liczby do posortowania, n zawiera ilość elementów do posortowania. #include <stdio.h> void sort(int a[], int elements ) { int i, j, temp; } i = 0; while( i < (elements - 1) ) { j = i + 1; while( j < elements ) { if( a[i] > a[j] ) { temp = a[i]; a[i] = a[j]; a[j] = temp; } j++; } i++; } main() { int loop; int numbers[] = { 10, 9, 8, 23, 19, 11, 2, 7, 1, 13, 12 }; printf("Before the sort the array was \n"); for( loop = 0; loop < 11; loop++ ) printf(" %d ", numbers[loop] ); } sort( numbers, 11 ); printf("\nAfter the sort the array was \n"); for( loop = 0; loop < 11; loop++ ) printf(" %d ", numbers[loop] ); 11 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 12. Zliczenia liczby wystąpień bitu ‘1’ w zmiennej ‘unsigned char’ #include <stdio.h> #include <stdlib.h> unsigned char bitcount(unsigned char); main() { unsigned char i8,count; int i; printf("Wprowadz liczbe (0 - 255 dziesietnie)\n"); scanf("%d",&i); if (( i < 0 ) || (i > 255)) { printf("Blad: Liczbs poza przezialem = %d\n", i); exit(1); } i8 = (unsigned char) i; count = bitcount(i8); printf("\n\nIlosc bitow ustawionych na '1' w %d = %d\n",i,count); } unsigned char bitcount(unsigned char x) { unsigned char count; for (count = 0; x!=0; x>>=1) if ( x & 01 ) ++count; return count; } Przykład 13. Rekurencyjne obliczanie silni #include <stdio.h> fact(int n) { if (n == 0) return(1); return(n * fact(n-1)); } main() { int n, m; printf("Wprowadz liczbe: "); scanf("%d", &n); m = fact(n); printf("Silnia z %d wynosi %d.\n", n, m); } 12 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 14. Określanie czasu obliczeń #include <stdio.h> #include <math.h> #include <time.h> main() { long i; time_t t1,t2; (void)time(&t1); for (i=1;i<=1000;++i) printf("%5ld %+15.13f %+15.13f %+20.18f\n",i, sin(i/100.), cos(i/100.), sqrt(sin(i/200.)*sin(i/200.)+cos(i/200.)*cos(i/200.))); (void)time(&t2); } printf("\nCzas potrzebny do obliczenie = %d sekund\n", (int)t2-t1); 13 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Całkowanie numeryczne h x0 x1 x2 Metoda trapezów: xN 1 ∫ f (x )dx = h 2 f x2 x1 Metoda Simpsona: xN +1 1 ∫ f (x )dx = h 3 f x3 1 x1 Metoda Simpsona 3/8: 3 ∫ f (x )dx = h 8 f x4 1 x1 1 + + + 1 f 2 + O h 3 f ′′ 2 ( ) 4 1 f 2 + f 3 + O h5 f ( 4 ) 3 3 ( ) 9 9 3 f 2 + f3 + f 4 + O h5 f ( 4) 8 8 8 ( Przykład 15. #define FUNC(x) ((*func)(x)) double trapzd(double (*func)(double), double a, double b, int n) { double x,tnm,sum,del; static double s; int it,j; if (n == 1) { return (s=0.5*(b-a)*(FUNC(a)+FUNC(b))); } else { for (it=1,j=1;j<n-1;j++) it <<= 1; tnm=it; del=(b-a)/tnm; x=a+0.5*del; for (sum=0.0,j=1;j<=it;j++,x+=del) sum += FUNC(x); s=0.5*(s+(b-a)*sum/tnm); return s; } } 14 ) UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Przykład 16. Całkowanie metodą trapezów i Simpsona #define EPS 1.0e-6 #define JMAX 20 double qtrap(double (*func)(double), double a, double b) { int j; double s,olds; olds = -1.0e30; for (j=1;j<=JMAX;j++) { s=trapzd(func,a,b,j); if (fabs(s-olds) < EPS*fabs(olds)) return s; if (s == 0.0 && olds == 0.0 && j > 6)return s; olds=s; } return 0.0; } float qsimp(float (*func)(float), float a, float b) { int j; float s,st,ost,os; ost = os = -1.0e30; for (j=1;j<=JMAX;j++) { st=trapzd(func,a,b,j); s=(4.0*st-ost)/3.0; if (fabs(s-os) < EPS*fabs(os)) return s; if (s == 0.0 && os == 0.0 && j > 6) return s; os=s; ost=st; } return 0.0; } int main() { double res1,res2; res1=qtrap(sin,0,1); res2=qsimp(sin,0,1); printf("%f, %f\n",res1,res2); } 15 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Generatory liczb pseudoloswych o rozkładzie równomioernym Ij+1 = a Ij + c Standardowe funkcje: #include <stdlib.h> void srand(unsigned seed); int rand(void); Aby otrzymać liczbę z przedziału [0,1]: x = rand()/(RAND_MAX+1.0); Przykład prostego generatora liczb pseudolosowych: unsigned long next=1; int rand(void) { next = next*1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } void srand(unsigned int seed) { next=seed; } Generator Park’a and Miller’a (okres 231-2 ≈ 2.1×109): #define #define #define #define #define #define IA 16807 IM 2147483647 AM (1.0/IM) IQ 127773 IR 2836 MASK 123459876 float ran0(long *idum) { long k; float ans; *idum ^= MASK; idum. k=(*idum)/IQ; *idum=IA*(*idum-k*IQ)-IR*k; if (*idum < 0) *idum += IM; ans=AM*(*idum); *idum ^= MASK; return ans; } Bardzo szybki, trywialny generator: idum = 1664525L*idum + 1013904223L; 16 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Sortowanie Metoda sortowania przez wstawianie proste Sortowanie tablicy w miejscu: void piksrt(int n, float arr[]) { int i,j; float a; for (j=2;j<=n;j++) { a=arr[j]; i=j-1; while (i > 0 && arr[i] > a) { arr[i+1]=arr[i]; i--; } arr[i+1]=a; } } Sortowanie tablicy w miejscu wraz z tablicą z nią sprzęŜoną: void piksr2(int n, float arr[], float brr[]) { int i,j; float a,b; for (j=2;j<=n;j++) { a=arr[j]; b=brr[j]; i=j-1; while (i > 0 && arr[i] > a) { arr[i+1]=arr[i]; brr[i+1]=brr[i]; i--; } arr[i+1]=a; brr[i+1]=b; } } 17 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Metoda sortowania Shell: void shell(unsigned long n, float a[]) { unsigned long i,j,inc; float v; inc=1; do { inc *= 3; inc++; } while (inc <= n); do { inc /= 3; for (i=inc+1;i<=n;i++) { v=a[i]; j=i; while (a[j-inc] > v) { a[j]=a[j-inc]; j -= inc; if (j <= inc) break; } a[j]=v; } } while (inc > 1); } 18 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Obliczanie miejsc zerowych Metoda bisekcji: #include <math.h> #define JMAX 40 //Maximum allowed number of bisections. float rtbis(float (*func)(float), float x1, float x2, float xacc) { int j; float dx,f,fmid,xmid,rtb; f=(*func)(x1); fmid=(*func)(x2); if (f*fmid >= 0.0) { printf("Błąd"); return 0.0; } rtb = f < 0.0 ? (dx=x2-x1,x1) : (dx=x1-x2,x2); for (j=1;j<=JMAX;j++)\ { fmid=(*func)(xmid=rtb+(dx *= 0.5)); if (fmid <= 0.0) rtb=xmid; if (fabs(dx) < xacc || fmid == 0.0) return rtb; } printf("Błąd"); return 0.0; } 19 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Metoda siecznych 2 f (x) 3 x 4 1 #include <math.h> #define MAXIT 30 float rtsec(float (*func)(float), float x1, float x2, float xacc) { void nrerror(char error_text[]); int j; float fl,f,dx,swap,xl,rts; fl=(*func)(x1); f=(*func)(x2); if (fabs(fl) < fabs(f)) { xl=x2; swap=fl; fl=f; f=swap; } else { xl=x1; rts=x2; } for (j=1;j<=MAXIT;j++) { dx=(xl-rts)*f/(f-fl); xl=rts; fl=f; rts += dx; f=(*func)(rts); if (fabs(dx) < xacc || f == 0.0) return rts; } printf("Błąd"); return 0.0; } 20 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Metoda stycznych (Newtona-Raphsona) f(x) 1 2 3 x #include <math.h> #define JMAX 20 float rtnewt(void (*funcd)(float, float *, float *), float x1, float x2,float xacc) { int j; float df,dx,f,rtn; rtn=0.5*(x1+x2); for (j=1;j<=JMAX;j++) { (*funcd)(rtn,&f,&df); dx=f/df; rtn -= dx; if ((x1-rtn)*(rtn-x2) < 0.0) { printf("Błąd"); return 0.0; } if (fabs(dx) < xacc) return rtn; } printf("Błąd"); return 0.0; } 21 UNIWERSYTET ŁÓDZKI KATEDRA INFORMATYKI Obliczanie kodu Gray’a 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 0000 0001 0011 0010 0110 0111 0101 0100 1100 1101 1111 1110 1010 1011 1001 1000 MSB 4 i 4 3 XOR 3 2 XOR 2 1 XOR 1 0 LSB XOR 0 G(i ) MSB 4 3 G(i ) 2 1 0 LSB 4 3 XOR 2 XOR i 1 XOR XOR 0 // For zero or positive values of is, return the Gray code of n; // if is is negative, return the inverse unsigned long igray(unsigned long n, int is) { int ish; unsigned long ans,idiv; if (is >= 0) return n ^ (n >> 1); ish=1; ans=n; for (;;) { ans ^= (idiv=ans >> ish); if (idiv <= 1 || ish == 16) return ans; ish <<= 1; } } 22