0

This code exemplifies the problem in a much simpler way (sorry for the previous one, it's too complicated). Anyway, note that out_b will print out correctly for any values of index between 0 to 958. The variable out_a, however, will always print out 36893488147419103232. And they're both of type DOUBLE. It looks like the + operation messes up the type of out_a. It won't work even if appendix is of type DOUBLE.

#include <stdio.h>
#include <stdlib.h>
#include <gsl/gsl_math.h>
#include <string.h>

double main (int argc, char *argv[]) {

    char *wrapper = "11111111111111111111111111111111111111111111111111111111111111111"; // 65 digits
    int appendix = atoi(argv[1]);

    int length = strlen(wrapper);

    double out_a = gsl_pow_int(2,length) + appendix;
    double out_b = gsl_pow_int(2,length + appendix);

    printf("%.0lf %.0lf\n", out_a, out_b);
}

Original question

This C program would compute the decimal equivalent to any binary input, as long as it's less than 64 digits... I fail to see why. Any help appreciated.

#include <stdio.h>
#include <stdlib.h>
#include <gsl/gsl_math.h>
#include <string.h>

long double main (int argc, char *argv[]) {

    char *wrapper = argv[1];

    static int *array, length, llo, i;
    static long double sum;

    while ( *wrapper && ( *wrapper == '0' ) ) wrapper++;

    length = strlen(wrapper);
    llo = length - 1;

    array = malloc((length*sizeof(*array))+1);

    for ( i = 0; i < length; i++ ) {
        if ( wrapper[i] >= '0' && wrapper[i] <= '1' ) {
            array[i] = wrapper[llo-i] - 48;
            sum += array[i] * gsl_pow_int(2,i);
        }

        else printf("Some error.\n");
    }

    free(array);

    printf("%.0Lf\n", sum);

}
  • 2
    Is there a specific section of the program you have a question about? – Sam Dufel Jan 21 '14 at 20:24
  • 1
    Have you tried stepping through the code, line by line, in a debugger? – Some programmer dude Jan 21 '14 at 20:24
  • Can 2 raised to power 64 be stored in an integer variable? I am not so sure about this. – Dinesh Jan 21 '14 at 20:24
  • 1
    Is your question "why does this work at all?" or "why does it fail when the input is larger than 64 bit?" ? – Guntram Blohm Jan 21 '14 at 20:25
  • My question is why does it fail for any binary inputs larger than 64 bit. I mean, the sum variable is double, the GSL power function returns a double... what gives? – Edward Tigert Jan 21 '14 at 21:44
  • experiment with the sizeof operator. You will see that sizeof(double) is only 64 bits. You can however use something like __int128. That will hold,... (drum roll) 128 bits. Also of interest may be [this](http://msdn.microsoft.com/en-us/library/cc953fe1.aspx) – ryyker Jan 21 '14 at 22:28

3 Answers3

1

Overall your code is ok, but:

  1. Return type of main should be int
  2. Don't really need array
  3. Should be if ( wrapper[llo-i] >= '0' && wrapper[llo-i] <= '1' ) {
  4. Initialze sum to 0

See: http://ideone.com/2ECduk

001
  • 13,291
  • 5
  • 35
  • 66
0

Regarding your question: I fail to see why. Any help appreciated.

Binary representation of an integer is shown as a series of 1s and 0s, each successively a higher power of 2.

eg: 10010 is equal to:

1      0       0       1       0    

(1*(2^4))+(0*(2^3))+(0*(2^2))+(1*(2^1))+(0*(2^0))
or: 16 + 0 + 0 + 2 + 0 or: 18

The section of code here: (from your example above)

for ( i = 0; i < length; i++ ) {//for each character in input (argv[1])
    if ( wrapper[llo-i] >= '0' && wrapper[llo-i] <= '1' ) {//test input for 1 or 0 (note llo-i correction)
        array[i] = wrapper[llo-i] - 48;//get next value into int array (note 48 is ascii value for 0)
                                       //results in placing either 1 or 0 into array[i]
        sum += array[i] * gsl_pow_int(2,i); //perform multiplication of appropriate power of 2 and add to sum
    }

    else printf("Some error.\n");
}

Just does the same thing. See comments to explain how.

ryyker
  • 22,849
  • 3
  • 43
  • 87
  • Thanks, but I understand that bit. My problem is in figuring out why inputs larger than 64 bits will fail, given the sum variable is able to store the supposed result. – Edward Tigert Jan 21 '14 at 21:50
  • Perhaps this ***[post](http://stackoverflow.com/questions/15601430/storing-and-printing-integer-values-greater-than-264)*** will answer your questions. Please be more specific in phrasing your questions. – ryyker Jan 21 '14 at 22:21
0

The GSL man page for gsl_pow_int explicitly states that this function is used for computing small integer powers efficiently, by computing things like x^8 as ((x^2)^2)^2). Even though it returns a double, it doesn't have unlimited precision.

EDIT

To be honest, this code is overly complicated, does some unnecessary memory management, and invokes undefined behavior in at least one respect. Do me a favor and see if the following code doesn't give you the results you expect:

#include <stdio.h>
#include <stdlib.h>

int main( int argc, char **argv )
{
  if ( argc < 2 )
  {
    printf( "USAGE: %s binary-string\n", argv[0] );
    exit(0);
  }

  long double result = 0;
  char *p = argv[1];

  while ( *p == '0' || *p == '1' )
  {
    result *= 2;
    result += *p++ - '0';
  }

  if ( *p && *p != '0' && *p != '1' )
  {
    printf( "%s is not a valid binary string; "
            "found non-binary digit %c at position %zu\n",
      argv[1], *p, (p - argv[1]) + 1 );
  }
  else
  {
    printf( "Result: %Lf\n", result );
  }

  return 0;
}

EDIT2

Here are the results on my system at home, up to 127 bits; I don't see any obvious discontinuity:

john@marvin:~/Development/Prototypes/C/converter$ input=1; let len=$(echo $input | wc -c)-1; while [ $len -lt 128 ]; do   echo "$input ($len)";   ./converter $input;   input=$input"0";   let len=$(echo $input | wc -c )-1; done
1 (1)
Result: 1.000000
10 (2)
Result: 2.000000
100 (3)
Result: 4.000000
1000 (4)
Result: 8.000000
10000 (5)
Result: 16.000000
100000 (6)
Result: 32.000000
1000000 (7)
Result: 64.000000
10000000 (8)
Result: 128.000000
100000000 (9)
Result: 256.000000
1000000000 (10)
Result: 512.000000
10000000000 (11)
Result: 1024.000000
100000000000 (12)
Result: 2048.000000
1000000000000 (13)
Result: 4096.000000
10000000000000 (14)
Result: 8192.000000
100000000000000 (15)
Result: 16384.000000
1000000000000000 (16)
Result: 32768.000000
10000000000000000 (17)
Result: 65536.000000
100000000000000000 (18)
Result: 131072.000000
1000000000000000000 (19)
Result: 262144.000000
10000000000000000000 (20)
Result: 524288.000000
100000000000000000000 (21)
Result: 1048576.000000
1000000000000000000000 (22)
Result: 2097152.000000
10000000000000000000000 (23)
Result: 4194304.000000
100000000000000000000000 (24)
Result: 8388608.000000
1000000000000000000000000 (25)
Result: 16777216.000000
10000000000000000000000000 (26)
Result: 33554432.000000
100000000000000000000000000 (27)
Result: 67108864.000000
1000000000000000000000000000 (28)
Result: 134217728.000000
10000000000000000000000000000 (29)
Result: 268435456.000000
100000000000000000000000000000 (30)
Result: 536870912.000000
1000000000000000000000000000000 (31)
Result: 1073741824.000000
10000000000000000000000000000000 (32)
Result: 2147483648.000000
100000000000000000000000000000000 (33)
Result: 4294967296.000000
1000000000000000000000000000000000 (34)
Result: 8589934592.000000
10000000000000000000000000000000000 (35)
Result: 17179869184.000000
100000000000000000000000000000000000 (36)
Result: 34359738368.000000
1000000000000000000000000000000000000 (37)
Result: 68719476736.000000
10000000000000000000000000000000000000 (38)
Result: 137438953472.000000
100000000000000000000000000000000000000 (39)
Result: 274877906944.000000
1000000000000000000000000000000000000000 (40)
Result: 549755813888.000000
10000000000000000000000000000000000000000 (41)
Result: 1099511627776.000000
100000000000000000000000000000000000000000 (42)
Result: 2199023255552.000000
1000000000000000000000000000000000000000000 (43)
Result: 4398046511104.000000
10000000000000000000000000000000000000000000 (44)
Result: 8796093022208.000000
100000000000000000000000000000000000000000000 (45)
Result: 17592186044416.000000
1000000000000000000000000000000000000000000000 (46)
Result: 35184372088832.000000
10000000000000000000000000000000000000000000000 (47)
Result: 70368744177664.000000
100000000000000000000000000000000000000000000000 (48)
Result: 140737488355328.000000
1000000000000000000000000000000000000000000000000 (49)
Result: 281474976710656.000000
10000000000000000000000000000000000000000000000000 (50)
Result: 562949953421312.000000
100000000000000000000000000000000000000000000000000 (51)
Result: 1125899906842624.000000
1000000000000000000000000000000000000000000000000000 (52)
Result: 2251799813685248.000000
10000000000000000000000000000000000000000000000000000 (53)
Result: 4503599627370496.000000
100000000000000000000000000000000000000000000000000000 (54)
Result: 9007199254740992.000000
1000000000000000000000000000000000000000000000000000000 (55)
Result: 18014398509481984.000000
10000000000000000000000000000000000000000000000000000000 (56)
Result: 36028797018963968.000000
100000000000000000000000000000000000000000000000000000000 (57)
Result: 72057594037927936.000000
1000000000000000000000000000000000000000000000000000000000 (58)
Result: 144115188075855872.000000
10000000000000000000000000000000000000000000000000000000000 (59)
Result: 288230376151711744.000000
100000000000000000000000000000000000000000000000000000000000 (60)
Result: 576460752303423488.000000
1000000000000000000000000000000000000000000000000000000000000 (61)
Result: 1152921504606846976.000000
10000000000000000000000000000000000000000000000000000000000000 (62)
Result: 2305843009213693952.000000
100000000000000000000000000000000000000000000000000000000000000 (63)
Result: 4611686018427387904.000000
1000000000000000000000000000000000000000000000000000000000000000 (64)
Result: 9223372036854775808.000000
10000000000000000000000000000000000000000000000000000000000000000 (65)
Result: 18446744073709551616.000000
100000000000000000000000000000000000000000000000000000000000000000 (66)
Result: 36893488147419103232.000000
1000000000000000000000000000000000000000000000000000000000000000000 (67)
Result: 73786976294838206464.000000
10000000000000000000000000000000000000000000000000000000000000000000 (68)
Result: 147573952589676412928.000000
100000000000000000000000000000000000000000000000000000000000000000000 (69)
Result: 295147905179352825856.000000
1000000000000000000000000000000000000000000000000000000000000000000000 (70)
Result: 590295810358705651712.000000
10000000000000000000000000000000000000000000000000000000000000000000000 (71)
Result: 1180591620717411303424.000000
100000000000000000000000000000000000000000000000000000000000000000000000 (72)
Result: 2361183241434822606848.000000
1000000000000000000000000000000000000000000000000000000000000000000000000 (73)
Result: 4722366482869645213696.000000
10000000000000000000000000000000000000000000000000000000000000000000000000 (74)
Result: 9444732965739290427392.000000
100000000000000000000000000000000000000000000000000000000000000000000000000 (75)
Result: 18889465931478580854784.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000 (76)
Result: 37778931862957161709568.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000 (77)
Result: 75557863725914323419136.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000 (78)
Result: 151115727451828646838272.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000 (79)
Result: 302231454903657293676544.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000 (80)
Result: 604462909807314587353088.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000 (81)
Result: 1208925819614629174706176.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000 (82)
Result: 2417851639229258349412352.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000 (83)
Result: 4835703278458516698824704.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000 (84)
Result: 9671406556917033397649408.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (85)
Result: 19342813113834066795298816.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (86)
Result: 38685626227668133590597632.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (87)
Result: 77371252455336267181195264.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (88)
Result: 154742504910672534362390528.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (89)
Result: 309485009821345068724781056.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (90)
Result: 618970019642690137449562112.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (91)
Result: 1237940039285380274899124224.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (92)
Result: 2475880078570760549798248448.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (93)
Result: 4951760157141521099596496896.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (94)
Result: 9903520314283042199192993792.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (95)
Result: 19807040628566084398385987584.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (96)
Result: 39614081257132168796771975168.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (97)
Result: 79228162514264337593543950336.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (98)
Result: 158456325028528675187087900672.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (99)
Result: 316912650057057350374175801344.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (100)
Result: 633825300114114700748351602688.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (101)
Result: 1267650600228229401496703205376.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (102)
Result: 2535301200456458802993406410752.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (103)
Result: 5070602400912917605986812821504.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (104)
Result: 10141204801825835211973625643008.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (105)
Result: 20282409603651670423947251286016.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (106)
Result: 40564819207303340847894502572032.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (107)
Result: 81129638414606681695789005144064.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (108)
Result: 162259276829213363391578010288128.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (109)
Result: 324518553658426726783156020576256.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (110)
Result: 649037107316853453566312041152512.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (111)
Result: 1298074214633706907132624082305024.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (112)
Result: 2596148429267413814265248164610048.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (113)
Result: 5192296858534827628530496329220096.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (114)
Result: 10384593717069655257060992658440192.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (115)
Result: 20769187434139310514121985316880384.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (116)
Result: 41538374868278621028243970633760768.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (117)
Result: 83076749736557242056487941267521536.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (118)
Result: 166153499473114484112975882535043072.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (119)
Result: 332306998946228968225951765070086144.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (120)
Result: 664613997892457936451903530140172288.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (121)
Result: 1329227995784915872903807060280344576.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (122)
Result: 2658455991569831745807614120560689152.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (123)
Result: 5316911983139663491615228241121378304.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (124)
Result: 10633823966279326983230456482242756608.000000
10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (125)
Result: 21267647932558653966460912964485513216.000000
100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (126)
Result: 42535295865117307932921825928971026432.000000
1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (127)
Result: 85070591730234615865843651857942052864.000000
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Nah, that's not the reason. The function works perfectly fine until up to 2^1023. – Edward Tigert Jan 21 '14 at 22:47
  • @EdwardTigert: see my edit. The code you posted has some problems, and these may be responsible for your issues. – John Bode Jan 21 '14 at 23:36
  • it behaves exactly like mine. Try to input any binary longer than 64 digits and you'll see. – Edward Tigert Jan 21 '14 at 23:55
  • @EdwardTigert: attached a sequence of runs from 1 bit to 127; I don't see any obvious discontinuity. What hardware are you running on? – John Bode Jan 22 '14 at 05:46
  • Try to input 10000000000000000000000000000000000000000000000000000000000000000 and 10000000000000000000000000000000000000000000000000000000000000001 and you'll see. The outcome is the same. – Edward Tigert Jan 22 '14 at 06:24
  • @EdwardTigert: I'm a moron; `long double` (at least on my system) only provides 18 decimal digits precision; those binary strings result in numbers that exceed that precision. Once you get past 64 bits, you exceed what the hardware can represent exactly (at least, we exceed what *my* hardware can represent exactly). – John Bode Jan 22 '14 at 13:16