zoukankan      html  css  js  c++  java
  • double转换long的疑问

      在lua(5.1.4)下面测试的时候使用0x100000000的时候出现了问题,打印结果很明显,如下所示:

    Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
    > print(0xffffffff)
    4294967295
    > print(0x100000000)
    4294967295
    > print(0x100000001)
    4294967295

      一个同事给出了答复,但是说是强制转换的原因。不是太明白,按照long long转换成int的形式就是截断,就不会出现上面哪种都是4294967285的结果。5.1.4的源代码关于计算0xffffffff到整形的函数如下所示:

    int luaO_str2d (const char *s, lua_Number *result) {
      char *endptr;
      *result = lua_str2number(s, &endptr);
      if (endptr == s) return 0;  /* conversion failed */
      if (*endptr == 'x' || *endptr == 'X')  /* maybe an hexadecimal constant? */
        *result = cast_num(strtoul(s, &endptr, 16));
      if (*endptr == '') return 1;  /* most common case */
      while (isspace(cast(unsigned char, *endptr))) endptr++;
      if (*endptr != '') return 0;  /* invalid trailing characters? */
      return 1;
    }

      查看源代码可以知道cast_num就是转换成lua_number类型,也就是double类型。另外,直接写了一个简单的c++代码来看strtoul函数的结果,结果果真就是一样的,被截断了。代码如下(请跳过,放在这里自己记录一下):

    void testStrtoul()
    {
            double a;
            char pNum[] = "0x1100000000";
            a = strtoul(pNum, 0, 16);
            printf("%f, %f, %d
    ", a, sizeof(double));
            a += 1;
            unsigned long c = (unsigned long)pow(2,32) + 1;
            /*
             (1)pow is double
             (2)double --> unsigned long, the result is 0xffffffff
            */
            double cc = pow(2, 31) * 4.0;
            printf("cc = %f
    ", cc);
            c = cc;
            printf("%f, %u
    ", a, c);
    }

      因此,想去搜索一下strtoul函数的实现,看到一篇帖子[1].发现返回值是unsigned long,也因此猜想是double转换long的时候出现的问题,直接使用上面的例子就可以看到结果。一开始也是怀疑double强制转换成long并且溢出的时候,结果都是0xffffffff,和这位仁兄想的是一样的[2]。
      但是,我非常不满意楼下给的回答:

    (1)2楼给的上下界的溢出理论

    (2)所谓的形象的比喻,水溢出杯子的理论

    (3)double和long存储结构不一样

      唯一有点含金量的是第三个回答,给不明白的人指出一条路去思考。起码去重现看一下这方面的知识点,其他的就不多说了,因为文章中用的java,而自己使用的是c++,所以不同之处就大敢多说了。因为从上面的解释来说,如果从截断角度分析都不行,4294967296即使是double的存储结构也不会有那么多bit位占1的,再怎么截断也不能够出现)XFFFFFFFF的情况。

      对于自己碰到的问题,原因可以从下面这个帖子[4]看到:就是strtoul函数在溢出的时候就直接返回ULONG_MAX,而这个值也恰好就是(0xFFFFFFFF)

    总结:

    (1)对于自己的问题strtoul函数是自定义返回ULONG_MAX才会出现一直返回一个固定值的情况和[2]中的LZ遇到的情况很相近

    (2)虽然说这些都是基本的计算机理论知识,但是还是要不断去探究其中的细节

    (3)对于java的那种情况,是不是强制转换中作了什么处理不发表评论了,没有发言权

    (4)c++中的double直接转换成long类型还是截断处理的,比如4294967296前置转化成long类型就是0,4294967295*2转换之后的结果为4294967294

    参考:

    [1]http://blog.csdn.net/czxyhll/article/details/7876084

    [2]http://bbs.csdn.net/topics/330076483

    [3]http://www.cnblogs.com/fly-height/articles/2340396.html

    [4]http://www.cplusplus.com/reference/cstdlib/strtoul/

  • 相关阅读:
    SQL查询SP代码
    MS SQL Server:查询死锁进程(转载)
    批编译、重新编译和计划缓存
    sql like获取以逗号分割的字段内的数据
    SQL Server 2005—数据库管理10个最重要的特点(转载)
    SQL2005数据库镜像配置脚本
    转:SQL 语句优化
    转:SQL SERVER什么时候写日志
    MDX查询几个经典示例
    尾日志备份和时间点还原
  • 原文地址:https://www.cnblogs.com/pk-run/p/4013953.html
Copyright © 2011-2022 走看看