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 == ‘\0‘) return 1;  /* most common case */
  while (isspace(cast(unsigned char, *endptr))) endptr++;
  if (*endptr != ‘\0‘) 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\n", 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\n", cc);
        c = cc;
        printf("%f, %u\n", 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/

时间: 2024-12-28 20:14:01

double转换long的疑问的相关文章

c++中double转换成string型(浮点数的格式化)

在日常编程中--包括对话框.关系数据库.金融程序.SMS程序及一切处理数据文件的程序,需要控制小数点后的小数位的情况非常普遍,本文中将要讲 解如何用简单的方法来控制小数位,另外,还要揭开字符串及数据精度的一点点小秘密. 问题的引出 如有一个函数,其可接受一个long double参数,并将参数转换为字符串,结果字符串应保留两位小数,例如,浮点值123.45678应该生成“123.45”这样的字符串.表面上看来 这是一个意义不大的编程问题,然而,如果真要在实际中派上用场,函数应设计为具有一定弹性,

关于c中 int, float, double转换中存在的精度损失问题

先看一段代码实验: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 #include<limits> #include<iostream> using namespace std; int main() {     unsigned int i = numeric_limits<unsigned int >::max();     float f = i;     unsigned

Java中float和double转换的问题

为什么double转float不会出现数据误差,而float转double却误差如此之大?   double d = 3.14; float f = (float)d; System.out.println(f); 输出结果是:3.14; float f = 127.1f; double d = f; System.out.println(d); 输出结果是:127.0999984741211 为什么结果会是这样呢? 如何避免这样的问题发生,让float转double能得到实际的数据? 解决办法

MFC,CString与int、double 转换

一.Cstring ---> double.int 在unicode字符集环境下: CString str; int a = _wtoi(str.GetBuffer()); double b = _wtof(str.GetBuffer()); 在多字节环境下: CString str; int a = atoi(str.GetBuffer()); double b = atof(str.GetBuffer()); 二.int.double--->CString int i=123; doubl

C++有符号和无符号数的转换

本文转自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题,被它们之间的转换原理和位移原理搞得头大了.真的很后悔本科的时候没有认真学习<计算机组成原理>/<计算机操作系统>等计算机基础课程.以下是我根据相关知识回顾和整理的材料,如有和某某的文章有雷同之处,请勿见怪.另外也希望看到这篇文章的同志们能够有所收获吧. 1 #include <

关于有符号数和无符号数的转换 - C/C++

转载自:http://www.94cto.com/index/Article/content/id/59973.html 1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题,被它们之间的转换原理和位移原理搞得头大了.真的很后悔本科的时候没有认真学习<计算机组成原理>/<计算机操作系统>等计算机基础课程.以下是我根据相关知识回顾和整理的材料,如有和某某的文章有雷同之处,请勿见怪.另外也希望看到这篇文章的同志们能够有所收获吧. #include <cst

关于有符号数和无符号数的转换

1.引例: 今天在做了一道关于有符号数和无符号数相互转换及其左移/右移的问题,被它们之间的转换原理和位移原理搞得头大了.真的很后悔本科的时候没有认真学习<计算机组成原理>/<计算机操作系统>等计算机基础课程.以下是我根据相关知识回顾和整理的材料,如有和某某的文章有雷同之处,请勿见怪.另外也希望看到这篇文章的同志们能够有所收获吧. #include <cstdio> #include <iostream> using namespace std; int ma

c语言-类型强制转换

强制转换的条件: 1.当所声明的类型不能满足所符值的变量时,需要转换声明的类型,以便能够存储变量. 例如:short存储的最大值为32767,但是所要符值大于32767时,short类型不符合,需要转换short类型.short MarSold = 61600;时就是错的. 2.丢失精度,当除以一个1.0和除以1是不同的.可能造成值的差别.整型除以整型只能得到整型,符值前先进行四舍五入后再符值.a=int/int,就算a是float但是得到是四舍五入后的值.可以将int转成float就可以得到精

String数据类型的转换

数据类型转换各种原始数据类型与String类型之间可以通过方法相互转换.valueOf()系列的静态方法用于从其它对象(原始数据类型对象)转换成字符串.例如:public static String valueOf(Booleanb)public static String valueOf(charc)public static String valueOf(inti)public static String valueOf(longl)public static String valueOf(