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

时间:2018-08-14 08:09:21

标签: c floating-point

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

输入:

float f= 8.947563;

输出:

uint32_t o1 = 8;
uint32_t o2 = 947563;

我想将所有这些结果存储在特定的寄存器中。

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

任何想法如何解决此问题? 谢谢。

4 个答案:

答案 0 :(得分:2)

您现在已经说过,该值是秒,具有纳秒级的分辨率,您需要删除整数部分并将其保留为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) ;

答案 1 :(得分:2)

函数modfffloat分为整数部分和小数部分(modf中的double)。如果您需要将.947563f转换为整数947563,则必须采取一些技巧。

一种通用的方法是将float文字转换为字符串,然后解析它。示例:

#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:   %d\n", integral);
  printf("Fractional: %d\n", fractional);
}

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

答案 2 :(得分:2)

让我们看一些浮点示例

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

这是当您进行以10为底的数学运算时o2来自的地方

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 %u\n",a,b);

给出

8 947563

让我整理一下负数。

答案 3 :(得分:-1)

通常我不使用c,所以我不知道是否有适当的方法来执行您想要的操作。但是,如果将浮点数转换为字符串并在该点处将其拆分,然后又将其都转换回整数或长整型或所需的大小,该怎么办。我知道这听起来不太好,但我认为这可能有效。