c-sprintf缩放整数.123打印为12,3



我有一个整数,表示十分之一。有没有一种快速的方法可以在最后一位之前添加一个小数点,而不是除以10,从而引入舍入误差(并浪费时间)?

像这样的魔术

snprintf(dest,len,"%d4.-1", 123) resulting in 12.3

原因是为了避免舍入误差,例如在货币中,金额在内部计算为整数美分,而不是英镑、欧元或美元的小数。

如果我没有记错COBOL,这里可以指定9990.00这样的格式,使1234打印为12.34,1打印为0.01。

void setup() {
Serial.begin(115200);
delay(1000);
uint16_t i16 = 0;
float f = 998;
for (i16 = 998; i16 < 1011; i16++) {
Serial.print(i16 / 1000);
Serial.print(" ");
Serial.print(f / 1000);
Serial.printf("  %0.3f %0.3f %0.7fn",i16/1000,f/1000,f/1000);
f = f + 1;
}
}

int/10仍然是int,所以123/10=12。

奇怪的是fprint("%0.2f",123/10)打印0.00

0 1.00 0.000 0.998 0.9980000 0 1.00 0.000 0.999 0.9990000 1 1.00 0.000 1.000 1.0000000 1 1.00 0.000 1.001 1.0010000 1 1.00 0.000 1.002 1.0020000 1 1.00 0.000 1.003 1.0030000 1 1.00 0.000 1.004 1.0039999 <--- Rounding error 1 1.00 0.000 1.005 1.0050000 1 1.01 0.000 1.006 1.0060000 1 1.01 0.000 1.007 1.0070000 1 1.01 0.000 1.008 1.0080000 1 1.01 0.000 1.009 1.0089999 <--- Rounding error 1 1.01 0.000 1.010 1.0100000

%0.6f不会给出舍入误差,但%0.7f会给出舍入误差。

因此,对于分数整数来说,如果有一个小数点移入的整数格式,那就太好了。

使用漂浮物有时会产生一些有趣的结果,就在昨天,我看到"水位预计将上升100000000002至12英尺"。

确保dest中有足够的空间!

int n = snprintf(dest, len, "%d", 123);
dest[n + 1] = 0;
dest[n] = dest[n - 1];
dest[n - 1] = '.';

或者,保存一行代码(感谢@bruno)

int n = snprintf(dest, len, "%d#", 123);
dest[n - 1] = dest[n - 2];
dest[n - 2] = '.';
snprintf (dest, len, "%3d.%01d", 123/10, 123%10)

请注意,使用fprint("%0.2f",123/10)时,由于%f转换说明符所期望的double类型与int123/10不匹配,OP代码具有未定义的行为。

整数除法定义明确,不会出现舍入误差。C标准库提供了div(), ldiv(), and lldiv()函数,可以在一次操作中计算整数除法和余数,为什么不利用它呢?

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
for (int i = 0; i < 1010; i += 500) {
for (int j = 0; j < 10; j++) {
int num = i + j;
div_t val = div(num, 10);
printf("%d --> %d.%dn", num, val.quot, val.rem);
}
}
return 0;
}

程序输出:

0 --> 0.0
1 --> 0.1
2 --> 0.2
3 --> 0.3
4 --> 0.4
5 --> 0.5
6 --> 0.6
7 --> 0.7
8 --> 0.8
9 --> 0.9
500 --> 50.0
501 --> 50.1
502 --> 50.2
503 --> 50.3
504 --> 50.4
505 --> 50.5
506 --> 50.6
507 --> 50.7
508 --> 50.8
509 --> 50.9
1000 --> 100.0
1001 --> 100.1
1002 --> 100.2
1003 --> 100.3
1004 --> 100.4
1005 --> 100.5
1006 --> 100.6
1007 --> 100.7
1008 --> 100.8
1009 --> 100.9

最新更新