是的我知道,对double值进行按位操作似乎是一个坏主意,但我确实需要它。C++通过长长指针中断输出双位输入
你并不需要阅读我的问题下一段落,只为好奇你们的:
其实我尝试一种特殊的MOD给Mozilla的Tamarin(ActionScript虚拟机)。其中,任何对象都有为其类型保留的前3位(例如,double是7)。这些位降低了原始数据类型的精度(int只有29位等)。对于我的国防部,我需要扩大这个区域2位。这意味着,例如,当您添加2个双打时,您需要将最后5位设置为零,进行数学运算,然后将结果重置。那么为什么^^
现在回到代码。 这里最小例子示出了非常类似的问题:
double *d = new double;
*d = 15.25;
printf("float: %f\n", *d);
//forced hex output of double
printf("forced bitwise of double: ");
unsigned char * c = (unsigned char *) d;
int i;
for (i = sizeof (double)-1; i >=0 ; i--) {
printf ("%02X ", c[i]);
}
printf ("\n");
//cast to long long-pointer, so that bitops become possible
long long * l = (long long*)d;
//now the bitops:
printf("IntHex: %016X, float: %f\n", *l, *(double*)l); //this output is wrong!
*l = *l | 0x07;
printf("last 3 bits set to 1: %016X, float: %f\n", *l, *d);//this output is wrong!
*l = *l | 0x18;
printf("2 bits more set to 1: %016X, float: %f\n", *l, *d);//this output is wrong!
在VisualStudio2008运行此时,第一输出是正确的。第二。 3rd对于十六进制和浮点数表示都会产生0,这显然是错误的。 4th和5th对于十六进制和浮点数也都为零,但修改后的比特以十六进制值显示。所以我想,也许这个类型混淆了这里的事情。所以2个输出:
printf("float2: %f\n", *(double*)(long long*)d); //almost right
printf("float3: %f\n", *d); //almost right
很好,他们表现出15.25,但它应该是15.2500000000000550670620214078。所以我想,嘿,这只是输出中的精确问题。允许修改位进一步向上:
*l = *l |= 0x10000000000;
printf("float4: %f\n", *d);
再次,输出是15.25(0000),和不15.2519531250000550670620214078。奇怪的是,另一个强制十六进制输出(见上面的代码)根本没有显示d的修改。所以我修了一下,意识到第31位(0x80000000)是我手动设置的最后一个。和神圣莫里,它实际上对输出有影响(15.250004)!
所以,虽然我略有偏差,仍然有很多混乱。 printf被破坏了吗?我在这里有一个大/小端的困惑吗?我无意中创建了某种缓冲区溢出?
如果有人有兴趣,在原来的问题(ta thing的事情,见上文),这几乎是相反的。在那里,最后三位已经被设置(表示双倍)。将它们设置为零可以正常工作(这是最初的实现)。将2更多地设置为零具有与上述相同的效果(总体值被置为零)。顺便说一下,它不是特定于输出的,而且数学运算似乎可以与这些地形数值一起工作(得到的2个数值的mul结果为0)。
任何帮助,将不胜感激。 问候。
谢谢迈克。那个流氓=实际上是一个复制粘贴错误,我发现在写这个问题的时候并没有在这里纠正它。 LL是我以前不知道的东西,所以非常感谢。 有什么奇怪的是:当我把这些%.30f放在printf的时候,他们没有再显示0.0,但实际上是15.25。 – 2012-07-27 11:04:15