- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
是的,我知道,对 double 值进行按位运算似乎是个坏主意,但我确实需要它。
我的问题你不需要阅读下一段,只是为了你们的好奇:
我实际上尝试了 Mozilla Tamarin(Actionscript 虚拟机)的特殊模组。其中,任何对象都为其类型保留前 3 位(例如,double 为 7)。这些位降低了原始数据类型的精度(int 只有 29 位等)。对于我的模组,我需要将这个区域扩展 2 位。这意味着,例如,当您添加 2 个 double 时,您需要将最后 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,这显然是错误的。十六进制和 float 的第 4 位和第 5 位也为零,但修改后的位显示在十六进制值中。所以我想,也许类型转换把这里的事情搞砸了。所以还有 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 坏了吗?我在这里有大/小端困惑吗?我是不是不小心造成了某种缓冲区溢出?
如果有人感兴趣,在最初的问题(狨猴问题,见上文)中,它几乎是相反的。在那里,最后三位已经设置(代表 double )。将它们设置为零可以正常工作(这是原始实现)。将 2 more 设置为零与上面的效果相同(总值降低为零)。顺便说一句,这不是特定于输出的,而且数学操作似乎也适用于那些底值(获得的 2 个值的乘积,结果为 0)。
如有任何帮助,我们将不胜感激。问候。
最佳答案
well, they show 15.25, but it should be 15.2500000000000550670620214078
默认情况下,%f
显示 6 位精度,因此您看不到差异。您还需要使用 ll
修饰符指定第一个参数是 long long
而不是 int
;否则,它可能会打印垃圾。如果您修复该问题并使用更高的精度,例如 %.30f
,您应该会看到预期的结果:
printf("last 3 bits set to 1: %016llX, float: %.30f\n", *l, *d);
printf("2 bits more set to 1: %016llX, float: %.30f\n", *l, *d);
last 3 bits set to 1: 0000000000000007, float: 15.250000000000012434497875801753
2 bits more set to 1: 000000000000001F, float: 15.250000000000055067062021407764
lets modify a bit further up:
*l = *l |= 0x10000000000;
printf("float4: %f\n", *d);
你有一个流氓 =
给出未定义的行为,所以这个值可能会或可能不会被修改(程序可能会或可能不会崩溃,打电话出去吃披萨,或者毁灭宇宙) .此外,如果您的编译器不兼容 C++11,则整型文字的类型可能不会大于 long
,它可能只有 32 位;在这种情况下,它将(可能)变为零。
修复这些问题(在我的情况下,按原样使用您的代码),我得到了预期的结果:
*l = *l | 0x10000000000LL; // just one assignment, and "LL" to force "long long"
printf("float4: %f\n", *d);
float4: 15.251953
Here是一个示范。
关于通过 long long 指针对 double 进行 C++ 按位操作会中断输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11685702/
我是一名优秀的程序员,十分优秀!