【问题标题】:Can't seem to figure out what's going on here似乎无法弄清楚这里发生了什么
【发布时间】:2014-01-22 19:16:48
【问题描述】:

这段代码以更简单的方式举例说明了这个问题(抱歉,前面的代码太复杂了)。无论如何,请注意 out_b 将正确打印 0 到 958 之间的任何索引值。但是,变量 out_a 将始终打印出 36893488147419103232。它们都是 DOUBLE 类型。看起来 + 操作弄乱了 out_a 的类型。即使附录是 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);
}

原始问题

只要小于 64 位,此 C 程序将计算与任何二进制输入等效的十进制数...我不明白为什么。任何帮助表示赞赏。

#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 的 64 次幂可以存储在整数变量中吗?我不太确定。
  • 您的问题是“为什么这会起作用?”或“当输入大于 64 位时为什么会失败?” ?
  • 我的问题是为什么任何大于 64 位的二进制输入都会失败。我的意思是,sum 变量是双倍的,GSL 幂函数返回一个双倍……什么给出?

标签: c arrays gsl


【解决方案1】:

总体来说你的代码还可以,但是:

  1. main 的返回类型应该是 int
  2. 真的不需要array
  3. 应该是if ( wrapper[llo-i] &gt;= '0' &amp;&amp; wrapper[llo-i] &lt;= '1' ) {
  4. sum初始化为0

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

【讨论】:

    【解决方案2】:

    关于您的问题:我不明白为什么。任何帮助表示赞赏。

    整数的二进制表示形式为一系列 1 和 0,每个依次是 2 的高次幂。

    例如:10010 等于:

    1      0       0       1       0    
    

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

    此处的代码部分:(来自您上面的示例)

    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");
    }
    

    只是做同样的事情。请参阅 cmets 来解释如何。

    【讨论】:

    • 谢谢,但我明白这一点。我的问题是弄清楚为什么大于 64 位的输入会失败,因为 sum 变量能够存储假定的结果。
    • 也许这个 post 会回答你的问题。请更具体地表达您的问题。
    【解决方案3】:

    gsl_pow_intGSL man page 明确指出此函数用于有效地计算 小整数幂,方法是将 x^8 之类的东西计算为 ((x^2)^2)^2)。即使它返回一个双精度,它也没有无限的精度。

    编辑

    说实话,这段代码过于复杂,做了一些不必要的内存管理,并且至少在一个方面调用了未定义的行为。帮我一个忙,看看下面的代码是否没有给你预期的结果:

    #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;
    }
    

    编辑2

    这是我在家系统上的结果,最多 127 位;我没有看到任何明显的不连续性:

    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
    

    【讨论】:

    • 不,这不是原因。该函数可以正常工作,直到 2^1023。
    • @EdwardTigert:查看我的编辑。您发布的代码存在一些问题,这些问题可能与您的问题有关。
    • 它的行为和我的一模一样。尝试输入任何长度超过 64 位的二进制文件,你会看到。
    • @EdwardTigert:附加了从 1 位到 127 位的运行序列;我没有看到任何明显的不连续性。你在什么硬件上运行?
    • 尝试输入1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001,您会看到。结果是一样的。
    猜你喜欢
    • 1970-01-01
    • 2011-07-08
    • 2021-06-04
    • 2020-07-26
    • 1970-01-01
    • 1970-01-01
    • 2014-07-28
    • 2016-03-12
    • 1970-01-01
    相关资源
    最近更新 更多