我想将浮点值存储在整数变量中并打印该整数变量,我想查看浮点值本身。可以做到吗?
答案 0 :(得分:4)
如果要查看orWhere
变量的位模式,可以执行以下操作:
float
答案 1 :(得分:3)
我想将浮点值存储在整数变量中
那是一个不好的开始。但是,如果所选的整数类型足够宽以容纳float
的表示形式,则可以将float
的字节复制到整数中。 memcpy
将是获得定义结果的更好方法之一。例如,如果float
和int
均为32位,则
float x = 1.2;
int i;
memcpy(&i, &x, sizeof(x));
这是我想到的最接近以整数形式存储float
的值的方式,可以容纳float
的整个范围,并且避免失去任何精度。
并打印 整数变量,我想查看浮点值本身。
我的意思是要打印float
值的人类可读的十进制表示形式。有多个标准库函数可将float
的内部表示形式转换为可打印的十进制表示形式,但是它们都将float
作为输入,而不是整数。当然,您可以将float表示形式复制到float
类型的对象中并使用它,但这似乎无法达到目的。但是,如果不这样做,就没有标准库函数可以满足您的要求。
它是什么 能不能做?
当然可以做到。尽管C没有定义使用C的运算符和标准库函数的方法,但是如果您假设float
的表示形式的详细信息,则可以编写您自己的函数来复制所需的方面(例如)printf
的总和,尽管这绝对是不平凡的。原则上,甚至可以编写代码来分析float
的实现表示,因此无需进行任何假设。但这是很多复杂代码的结果,而仅通过将float
值存储在float
对象中即可更好地获得结果。
答案 2 :(得分:2)
来自评论:
我的一个朋友问我这是否可行,我尝试了一下,但是找不到解决方法,就是为什么
通过严格回答,您可以这样:
#include <stdio.h>
int main(void) {
int x; // Here is where we store the data
float *p = (float*) &x; // Make a float pointer point at the integer
*p = 42.67; // Pretend that the integer is a float and store the value
printf("%f\n", *(float*)&x); // Print what's inside x, pretending it's a float
}
这样写不是一个好主意。请注意,这是未定义行为,因此C编译器基本上可以自由生成所需的任何垃圾。它只是偶然(几乎)始终在实践中起作用的那些不确定行为之一。至少对于预期的目标平台。我严格地写了这个答案以表明它是可能的,但是正如我所说的,它是UB,并且不是可移植的。
如果sizeof(float)> sizeof(int),这肯定会失败,但是我认为这是实现定义的。如果是这种情况,请选择一个至少与浮动类型一样大的整数类型。
值得一提的是,Quake引擎中确实存在类似的东西。即使不是约翰·卡马克(John Carmack)提出,也被称为Carmack hack。但是在那些日子里,CPU周期比可移植性更重要。代码如下(带有原始注释):
float Q_rsqrt( float number )
{
long i;
float x2, y;
const float threehalfs = 1.5F;
x2 = number * 0.5F;
y = number;
i = * ( long * ) &y; // evil floating point bit level hacking
i = 0x5f3759df - ( i >> 1 ); // what the fuck?
y = * ( float * ) &i;
y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration
// y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed
return y;
}
答案 3 :(得分:1)
是否可以将浮点值存储在int变量(?)
使用union
。
当float
的大小与可用的uintN_t
类型匹配时,就没有问题。
float a = ...;
// i want to see the float value itself.
printf("%e %a\n", a, a); // Use exponential notation
// to an integer type
assert(sizeof(float) == sizeof(uint32_t));
union {
float f;
uint32_t u;
} x = { a };
unsigned long ul = x.u;
// print that integer variable
printf("%lX\n", ul);
// and back again
union {
float f;
uint32_t u;
} y = { .u = (uint32_t) ul };
float f = y.f;
printf("%e %a\n", f, f);
请注意,printf("%lX\n", ul);
将打印出与printf("%e %a\n", a, a);
明显不符的内容。
答案 4 :(得分:0)
首先,请记住int
和float
值的二进制表示形式彼此非常不同。整数值1
和浮点值1.0
的表示形式看起来并不相同。假设32位int
和float
以及IEEE-754表示形式,我们得到:
1: 0000 0000 0000 0000 0000 0000 0000 0001 (0x00000001)
1.0: 0111 1111 1000 0000 0000 0000 0000 0000 (0x3f800000)
为float
对象分配int
值截断小数部分-如果您编写类似的内容
int b = 1.2f; // 0x3f99999a
存储在b
中的值为1
(0x00000001
)。如果您尝试将b
分配回float
,例如
float f = b;
然后存储在f
中的值为1.0
(0x3f800000
),不是 1.2
(0x3f99999a
)
因此,您无法通过简单的分配将float
值存储在int
对象中。
如果int
的宽度至少等于int
,则可以在float
对象 中存储浮点值的位模式。 memcpy
,可以使用printf
或某种形式的体操(如其他答案所示)。但是,如果尝试使用带有%d
转换说明符的float
打印该值,则输出将不会表示该1.2
值(1067030938
),将表示该位模式($ sudo npm
sudo: npm: command not found
$ sudo nvm
sudo: nvm: command not found
$ sudo balena
sudo: balena: command not found
)表示的整数值。
没有安全,定义明确的标准方法将浮点值存储在整数对象中,并且像对待其他任何浮点对象一样对待它。 C可能不像其他语言那样强类型化,但是它的足够强足够强大,因此您必须依靠不安全的技巧来解决它(如其他答案所示)。