C-32位计算机上的无符号长到双精度
嗨,我有两个问题:C-32位计算机上的无符号长到双精度,c,double,unsigned,primitive,C,Double,Unsigned,Primitive,嗨,我有两个问题: uint64\u t vs double,哪一个覆盖正数的范围限制更高 如果只需要double的整数部分,如何将double转换为uint64\t 由于double的定义,直接铸造显然不起作用 很抱歉给您带来任何困惑,我说的是32位机器上的64位双精度C 例如: //operation for convertion I used: double sampleRate = ( (union { double i; uint64_t s
很抱歉给您带来任何困惑,我说的是32位机器上的64位双精度C 例如:
//operation for convertion I used:
double sampleRate = (
(union { double i; uint64_t sampleRate; })
{ .i = r23u.outputSampleRate}
).sampleRate;
//the following are printouts on command line
// double uint64_t
//printed by %.16llx %.16llx
outputSampleRate 0x41886a0000000000 0x41886a0000000000 sampleRate
//printed by %f %llu
outputSampleRate 51200000.000000 4722140757530509312 sampleRate
因此,这两个数字保持相同的位模式,但当以小数形式输出时,uint64_t是完全错误的。
谢谢。由于8字节IEEE 754的值范围为4.94065645841246544e-324d到1.79769313486231570e+308d(正或负),所以双精度
可以容纳比uint64\u t
大得多的数字。但是,如果在该范围内添加较小的值,您会感到意外,因为在某些点上,精度将无法表示例如1的加法,并将向下舍入到较低的值,基本上使循环稳定地增加1
此代码例如:
#include <stdio.h>
2 int main()
3 {
4 for (double i = 100000000000000000000000000000000.0; i < 1000000000000000000000000000000000000000000000000.0; ++i)
5 printf("%lf\n", i);
6 return 0;
7 }
#包括
2 int main()
3 {
4表示(双i=1000000000000000000000000.0;i<10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
5 printf(“%lf\n”,i);
6返回0;
7 }
给我一个100000000000000536162204393472.000000的恒定输出。这也是为什么我们在数学中有nextafter和nexttoward函数。您还可以在那里找到ceil和floor函数,理论上,这将允许您解决第二个问题:删除分数部分
然而,如果您真的需要保存大量的数字,您应该转而考虑bigint实现,例如。bigint被设计用来对非常大的整数进行运算,像一个加法这样的运算,即使对于非常大的值,也会真正增加数字
uint64\u t vs double,哪一个覆盖正数的范围限制更高
uint64\u t
,在支持的情况下,具有64个值位、无填充位和无符号位。它可以表示0和264-1之间的所有整数(包括0和264-1)
实际上,所有现代C实现都以IEEE-754 64位二进制格式表示double
,但C不要求也不认可该格式。然而,这种情况非常普遍,因此假设这种格式是相当安全的,并且可能只是针对定义FP特性的宏进行一些编译时检查。为了平衡这个答案,我将假设C实现确实使用了这种表示
IEEE-754二进制双精度提供53位尾数,因此它可以表示0到253-1之间的所有整数。但是,它是一种浮点格式,具有11位二进制指数。它所能代表的最大数字是(253-1)*21023,或接近21077。从这个意义上说,double
的范围比uint64_t
大得多,但是0与其最大值之间的绝大多数整数不能精确表示为double
s,包括几乎所有可以由uint64_t
精确表示的数字
如果只需要double的整数部分,如何将double转换为uint64\t
您可以简单地赋值(转换是隐式的),也可以显式地强制转换(如果您想明确转换发生):
double my_double = 1.2345678e48;
uint64_t my_uint;
uint64_t my_other_uint;
my_uint = my_double;
my_other_uint = (uint64_t) my_double;
double
值的任何小数部分都将被截断。如果整数部分可表示为uint64\u t
,则整数部分将被精确保留;否则,行为是未定义的
您介绍的代码使用一个并集来覆盖双精度
和uint64\u t
的存储。这并不是天生的错误,但它不是在两种类型之间转换的有用技术。强制转换是C进行所有非隐式值转换的机制。您是指C中指定的double
,还是ieee754 binary64浮点中指定的double
?对于#2,您是否尝试只分配给double变量?您所说的“直接强制转换显然不起作用”是什么意思?它怎么不起作用?举一个数字的例子,当你将它转换为double时,你得到了什么,以及你如何检查它的值。double
有一个更大的“最大值”。但是“掩护”?它的精度与该值的对数成正比。因此,在某一点上,即使是“整个”部分也会受到不精确的影响。“在32位机器上使用C双精度”-这并不能澄清任何问题!C11标准草案n1570 6.3.1.4实浮点和整数1当实浮点类型的有限值转换为除_Bool以外的整数类型时,小数部分被丢弃(即,该值被截断为零)。如果整数部分的值不能用整数类型表示,则行为未定义。@EOF,谢谢您的更正。我已经更新了我的答案。