C语言 将浮点数拆分为两个简单的整数?



我正在尝试实现一个执行以下操作的 c 函数:

输入:

float f= 8.947563;

输出:

uint32_t o1 = 8;
uint32_t o2 = 947563;

我想将这些结果中的每一个存储在特定的寄存器中。

我找到了一些解决方案,例如 modf 函数,但它并没有真正解决我的问题,因为它的 o2 将是 0.947563 而不是 947563。 此外,分数后面的位数可能会根据用户输入而有所不同,因此我不能简单地设置一个规则将 0.947563 乘以 1000000,因为它不适用于具有较大分数的数字,例如 8.947556333。

知道如何解决这个问题吗? 谢谢。

函数modfffloat分解为整数和分数部分(modf表示double(。如果您需要将.947563f转换为整数947563,则必须执行某种技巧。

一种通用的方法是将浮点文本转换为字符串,然后对其进行解析。例:

#include <stdio.h>
static int modff_int (const char* value, int* iptr)
{
int fractional;
sscanf(value, "%d.%d", &fractional, iptr);
return fractional;
}
#define FLOAT_TO_STR(f) #f  // simplified version that only works with float literals

int main (void)
{
int integral;
const char* str = FLOAT_TO_STR(8.947563f);
int fractional = modff_int(str, &integral);
printf("Integral:   %dn", integral);
printf("Fractional: %dn", fractional);
}

然而,这比简单地将浮点数.947563f乘以一个常数要慢得多。

让我们看一些浮点示例:

1.5
0x3FC00000
0 01111111 10000000000000000000000
1.10000000000000000000000<<0
1.10000000000000000000000
1.8
0x3FE66666
0 01111111 11001100110011001100110
1.10000000000000000000000<<0
1.10000000000000000000000
2.1
0x40066666
0 10000000 00001100110011001100110
1.00001100110011001100110<<1
10.0001100110011001100110
12.3456
0x41458794
0 10000010 10001011000011110010100
1.10001011000011110010100<<3
1100.01011000011110010100

那么,你想得到什么呢?

12.3456 1100.01011000011110010100 你的两个uint32_ts是0b1100和0b01011000011110010100,前者是你想要的形式,但后者呢? 您的示例是十进制的,当然与计算机上的浮点数无关。

您的号码 8.947563

0x410F2938
0 10000010 00011110010100100111000
1.00011110010100100111000<<3
1000.11110010100100111000
f = 8.947563
o1 = 1000
o2 = 00000000000011100111010101101011

11110010100100111000
11100111010101101011

不相等。 前者是分数,因此需要进行一些操作。

11110010100100111000/100000000000000000000*11110100001001000000

0xF2938 * 0xF4240 

不适合 32 位,因此我们必须将其升级到 64 位。

0000000000000000000000001110011101010110101100101011111000000000/100000000000000000000

这就是O2的来源,当你做10个基数数学时

1110011101010110101100101011111
11100111010101101011

本来可以完成 32 位

0xF293*0xF424
11100111010101100011100010101100

并切断前 20 位,您得到947563 O2

11100111010101100011100010101100
11100111010101101011

因此,如果您总是想要 6 位数字,那么取分数乘以 1000000 并从底部修剪掉正确数量的位数。 对于单个尾数,尾数开始为 23 位,对于您的数字,指数为 3,因此尾数中剩余 20 位作为分数。 上面欺骗了一些你想将这些数字调整为已知对齐方式,就像你在做普通浮点数学时一样,例如

0xF2938000*0xF4240000;

1110011101010110101100101011111000000000000000000000000000000000

我们砍掉前 32 位:

11100111010101101011001010111110

然后取前 20 位:

11100111010101101011 result
11100111010101101011 o2

0xF2938 * 0xF4240同样很好0xF293*0xF424可能会给出与预期不同的结果。

如果这是您想要的,十进制中的 6 位数字,然后这样做:

double x, y, z;
uint32_t a,b;
x = 8.947563;
y = modf(x, &z);
a = z;
b = y*1000000.0;
printf("%u %un",a,b);

这给了:

8 947563

我会让你整理出负数。

正如您现在所说,该值是纳秒分辨率的秒,您需要删除整数部分并将其保留为 o1,然后乘以 1E9,加上 0.5,然后将整数部分作为 o2。添加 0.5 是四舍五入到最接近的纳秒,而不是截断。 请注意,变量f应该是double而不是float,因为float只能存储大约 7 位有效数字。

#define TEN_POWER_9 ((double)(1e9))    
o1 = int(f) ;
o2 = int(((f - (double)o1) * TEN_POWER_9) + 0.5) ;

通常我不使用 c,所以我不知道是否有正确的方法来做你想要的。但是,如果您将浮点数转换为字符串并在点处拆分它们,然后将两者转换回整数或长整型或任何您想要的内容,该怎么办?我知道这听起来不太好,但我认为这可以奏效。

最新更新