C++ 设置精度并剪裁尾随零,但不打印指数
我需要:C++ 设置精度并剪裁尾随零,但不打印指数,c++,c,floating-point,printf,cout,C++,C,Floating Point,Printf,Cout,我需要: 设置精度,使浮点数四舍五入到第一百位(0.111打印为0.11) 剪辑尾随零(1.0打印为1) 从不打印指数(1000.1打印为1000.1) printf(“%.2f\n”,输入);//处理1和3,但不处理2 printf(“%.2g\n”,输入);//处理1和2,但不处理3 cout我不知道有哪种格式说明符可以满足您的要求 在将值传递给单独的格式说明符之前预消化这些值可能会起作用。例如: 将原始浮点数乘以100并四舍五入到最接近的整数 分配给nScaled(int) 将mod(n
printf(“%.2f\n”,输入);//处理1和3,但不处理2
printf(“%.2g\n”,输入);//处理1和2,但不处理3
cout我不知道有哪种格式说明符可以满足您的要求
在将值传递给单独的格式说明符之前预消化这些值可能会起作用。例如:
- 将原始浮点数乘以100并四舍五入到最接近的整数
- 分配给nScaled(int)
- 将mod(nScaled,100)赋值给另一个整数n分数
- 将nScaled/100指定给另一个整数nWhole
您可能已经知道了。C11标准中提到了%f
和%f
(7.21.6.1:8):
表示浮点数的双参数转换为样式中的十进制表示法[−]ddd.ddd,其中小数点字符后的位数等于精度规格。如果精度缺失,则取6;如果精度为零且未指定#标志,则不显示小数点字符。如果显示小数点字符,则至少在其前显示一位数字。该值四舍五入到适当的位数
下面是一个C代码段,它在malloc
ed bloct
中生成您想要的内容,您需要在以后释放它。如果您使用C99编写,还可以考虑使用可变长度数组
下面的代码不会对转换引入任何额外的近似值(如果您的printf
将正确的四舍五入转换为十进制,下面的代码也会这样),并且适用于所有浮点值
#include <stdio.h>
#include <stdlib.h>
…
int len = snprintf(0, 0, "%.2f", input);
if (len < 0) fail();
char *t = malloc((size_t)len + 1);
if (!t) fail();
if (sprintf(t, "%.2f", input) < 0) fail();
len--;
if (t[len] == '0') {
len--;
if (t[len] == '0') {
len--;
if (t[len] == '.') len--;
}
t[len + 1] = '\0';
}
#包括
#包括
…
int len=snprintf(0,0,“%.2f”,输入);
如果(len<0)失败();
char*t=malloc((大小)len+1);
如果(!t)失败();
如果(sprintf(t,“%.2f”,输入)<0)失败();
蓝--;
如果(t[len]=“0”){
蓝--;
如果(t[len]=“0”){
蓝--;
如果(t[len]='.')len--;
}
t[len+1]='\0';
}
我认为另一种选择是使用asprintf()函数:它自己动态分配一个适当长度的字符串。一旦字符串被存储,尾随的零/点可以被截断:
...
float num;
...
char *digits;
int i=asprintf(&digits, "%.2f", num)-1;
for(; digits[i] !='.'; i--)
if (digits[i] == '0') digits[i] = NULL; else break;
if (digits[i] == '.') digits[i] = NULL;
printf("%s\n", digits);
free(digits);
...
<> P>遗憾的是,没有强制流使用<代码> Prtff < /C> >代码> %F行为。所以,唯一的处理方法是在必要时手动修剪小数点。我添加了一个C++代码示例来处理这个:
string fullfloat(static_cast<size_t>(log10(numeric_limits<declval(input)>::max())) + 5U, '\0'); // Adding 1 for the 10s place, 1 for the '.' 2 for the decimal places, and 1 for the null
const size_t length = size(fullfloat) - sprintf(data(fullfloat), "%.2f", input );
*(--mismatch(rbegin(fullfloat) + length, next(rbegin(fullfloat), 3U + length), "00.").first) = '\0';
我不明白printf(“%.2f\n””,
如何在第3点失败。当我使用它时,它不会打印指数(Mac OS X上的叮当声)打印1E267或1E-267.@ PascalCuoq谢谢我改变了顺序,忘记了更改附加代码。我现在已经修复了。@ JunWrices我几乎做了同样的事情,然后我认为一个纯C解决方案可能是OP可以接受的,即使问题确实包含一些C++。现在我已经用C和你编写了一个解决方案。编辑让我的解决方案看起来很有意义。Pascal:…好吧,我同意我太匆忙了。OP可能只是更清楚一些。(我看到海报在要求C++时发出抱怨,并且提交了一个纯C解决方案,IMO确实应该至少是一样好。)这样做的问题是,乘以100可能不精确,并且结果不必符合int
或任何可用的整数类型。您还可以从使用%f
打印浮点数的字符串中删除尾随的零和点,至少它适用于所有数字。此外,它还可以当1时产生错误的结果≤ 零碎的≤ 9、我使用<代码> SpaTFF。我正在用C++来完成你用C++做的事情。如果你想用C++风格来做这个,我会接受你的答案,如果不是,我可以发布我自己的答案。你需要一个你真的没有理由将你的问题标记为“C”的标签。事实上,这两个标签的追随者(至少是我和Jongware)如果您避免在将来的问题上同时添加两个标签,除非它们确实都与您的问题相关,我将不胜感激。似乎我用于此问题的任何解决方案都必须使用printf
变体。我不知道snprintf
。我曾希望会有其他的老派stdio.h
魔术这就解决了这个问题,而无需我编写代码来修剪尾随的0。看起来情况并非如此,但这是我使用C
标记的基本原理。@JonathanMee:你看到了非常棒的答案吗(至少其中一些)到?您可能可以根据自己的喜好调整其中一个。@Jongware是一个优雅、简约、正确的四舍五入解决方案(与您链接到的问题中所有可疑的答案不同)可以在musl库中找到:这在Linux平台上是可行的。但由于缺乏可移植性,它实际上不如@PascalCuoq或我的解决方案。
string fullfloat(static_cast<size_t>(log10(numeric_limits<declval(input)>::max())) + 5U, '\0'); // Adding 1 for the 10s place, 1 for the '.' 2 for the decimal places, and 1 for the null
const size_t length = size(fullfloat) - sprintf(data(fullfloat), "%.2f", input );
*(--mismatch(rbegin(fullfloat) + length, next(rbegin(fullfloat), 3U + length), "00.").first) = '\0';
cout << data(fullfloat);