java - Collatz and other sequences: how to get more precision easily and avoid segfault? -
here's simple c program created old java code (my first c program, nice ;) ). runs faster corresponding java code, java allows me more precise (i'm using longs in java, too) before crashes.
to surprise, java code doesn't crash until input exceeds 170,000,000. c code can't handle on 1,050,000. suggestions on making c code run better without needing crazy libraries? thanks!
#include <stdio.h> #include <string.h> /* lets me use memset */ #include <stdlib.h> /* home of strtoull */ /* segfault 11 after 1047993 (not anymore!!) */ unsigned long long getnext( unsigned long long x ); unsigned long long getnext( unsigned long long x ) { if (x == 1) { return 1; } if (x % 2 == 0) { return x/2; } return (3 * x + 1); } int main(int argc, char *argv[]) { int argind; ( argind = 0; argind < argc; argind++ ) { unsigned long long intrange; intrange = strtoull(argv[argind], null, 10); /** improper allocation of memory. fixed directly below. marcus! * unsigned long long lengths[intrange+1]; * memset(lengths, 0, sizeof(lengths)); */ unsigned long long *lengths= malloc((intrange+1) * sizeof(unsigned long long)); /* ptr points mem. location of lengths array. */ memset(lengths, 0, (intrange+1) * sizeof(unsigned long long)); unsigned long long longestlen[2]; unsigned long long seqindex; unsigned long long origdex; longestlen[0] = 0; longestlen[1] = 0; (origdex = 2; origdex <= intrange; origdex++) { seqindex = origdex; while ( seqindex > 1 ) { lengths[ origdex ] += 1; seqindex = getnext(seqindex); if ( seqindex <= intrange ) { if ( lengths[ seqindex ] > 0) { lengths[ origdex ] = lengths[ origdex ] + lengths[ seqindex ]; if ( lengths[origdex] > longestlen[1] ) { longestlen[0] = origdex; longestlen[1] = lengths[origdex]; } seqindex = 1; continue; } } } } if(longestlen[0] > 0 ){ printf("longest collatz sequence first %llu positive integers found @ %llu length %llu. \n", intrange, longestlen[0], longestlen[1]); } } return 0 ; }
if let program run through debugger (in case:
gcc -o collatz -g collatz.c gdb --args collatz 2000000 $run ...segfault @ memset(lengths,0,sizeof(lengths))...
), you'll see segfault happens when try access lengths!
the point you're doing dynamic memory allocation arrays wrong; that's bit tricky in c (which why recommend people coming other languages learn modern c++ rathern c).
you should do
unsigned long long *lengths = malloc(...);
to give freshly allocated memory.
also, sizeof(lengths)
wrong, since size of pointer address of beginning of array. use sizeof(unsigned long long)
instead. of course, code must read memset(lengths, 0, sizeof(unsigned long long)*(intrange+1))
set intrange+1
times amount of bytes unsigned long long
occupies 0
byte.
for details on malloc
, can use man malloc
if you're on system has man
; generally, have "release" memory allocate using malloc
after usage. in case, upon termination of program it's done automatically, more complex software, not calling free(ptr)
on you've acquired type *ptr = malloc(...)
after no longer need memory memory leak.
again, that's typical c problem. if write code in c++, will, @ no performance penalty @ all, ability use things std::vector
give variable-sized arrays automatic construction , value fill, automatically deallocated upon leaving scope in declared.
Comments
Post a Comment