如何在C中自动缩放浮点值?

时间:2018-09-26 14:05:36

标签: c floating-point precision

我正在研究一种通过16位ADC测量电压的嵌入​​式设备。 以3.3V为参考,我的分辨率为50uV。因此,该设备可以在50uV至3.3V的范围内进行测量,因此,根据当前值,我需要对其进行格式化并以mV或uV或V等格式显示。

该值为浮点数。

是否有现成的库API可以做到这一点?或者我应该编写自己的代码?

1 个答案:

答案 0 :(得分:2)

  

如何在C语言中自动缩放浮点值?

自动转换到1000s的幂在转换过程中有一些细微的考虑,甚至在转换过程中都进行了OP编码,在极端情况下可能会失败。

让我们尝试一个稍微不同但更简单的目标:以30.0个有效数字并以1000.0的幂进行打印

// example output
1.00
9.99
10.0
99.9
100.
999.
1.00k
9.99k
10.0k
...

代码可以尝试使用log()等以自己的数学方式执行此操作,但是在接近9.995、99.95、999.5的情况下将始终失败。

sprintf()完成繁重的工作,然后使用字符串操作。


第一步是使用"%e"

打印到字符串
//            sgn  dig  . digs  e  sgn expo \0 
#define FLT_E2 (1 + 1 + 1 + 2 + 1 + 1 + 5 + 1)
// let us double buffer size as there is little reason to be stingy here.
char buf[FLT_E2 * 2];  

//                           v--- 2 digits after the lead digit
snprintf(buf, sizeof buf, "%.2e", some_float);

下一步是将字符串分成3部分,并使用"%n"记下小数点和'e'的偏移量。

int whole, frac, expo, dp, e;
if (sscanf(buf, "%d%n.%d%ne%d", &whole, &dp, &frac, &e, &expo) != 3) {
  // value is some non-finite like infinity or not-a-number.
  printf("%e", some_float);  
  return;
}

现在将expo下移至3的倍数并移动小数点。

while (expo%3) {
  expo--;
  buf[dp] = buf[dp+1];
  buf[++dp] = '.';
}

'e'转换为各种SI prefix

// TBD code to handle expo out of range [-24 24], left for OP.

char prefix = "yzafpnum kMGTPEZY"[(expo - -24)/3];
if (prefix != ' ') buf[e++] = prefix;
buf[e] = '\0';

现在打印

printf("%s", buf);

尽管这些未经检查的代码片段在此处有很多细节,但最终的代码仍留给OP形成。

高级问题包括:
  处理特定于语言环境的小数点,例如','
  指数outside [-24 ... 24]。
  μ对u。