示例输入字符串:
char *str = "12345.567675";
如果我需要小数点后 3 位的精度,则所需的输出:
str = "12345.568";
有没有办法在不将字符串转换为字符串的情况下做到这一点double
?
是的,在高层次上:
1. 搜索 '.' 在字符串中。
2.如果'.'的位置 + 3 小于您所做的长度。
3. 否则,将字符串连接到 '.' 的位置 + 3.
4. 这里很棘手:您需要检查下一个字符是否存在,('.' + 4),如果它的值 >= 5,则转到 4.1(否则转到 5)
4.1。将字符串复制到一个在左侧多出一个空格的新字符串(因为在 '4' 循环中 9.9999 将更改为 10.0000),并将指针 (P) 设置为该字符串中的最后一个字符。
4.2. 如果 *P 在 0 到 8 之间,则向其添加 1 并转到 5。
4.3。如果 *P 为 9,则将其设置为零,将指针向左移动一 (-1) 并转到 4.2
4.4。如果 *P 是 '.',将指针向左移动一 (-1) 并转到 4.2
5.删除小数点右边的所有0(如果需要,小数点自己删除),你就完成了!!!
6.删除所有内容,并使用双重转换方法...
您可以使用递归来做到这一点。
void roundstr(std::string& strp) {
char clast;
char nlast;
int sl(strp.length()), ipos(0);
if (strp[sl - 1] == '.') { // skip the dot
strp.erase(strp.end() - 1);
nlast='.';
roundstr(strp);
return;
}
if (strp[sl - 2] == '.') { // handle dot is next char
ipos = 1;
}
if (sl == 1) { // handle first char
nlast = '0'; // virtual 0 in front of first char
clast = strp[1];
} else {
clast = strp[sl - 1]; // current (last) char
nlast = strp[sl - 2 - ipos]; // next to last char
}
if (clast >= '5') { // need to operate only if meet 5 or larger, otherwise stop
nlast++;
strp.erase(strp.end() - 1); // remove the last char from the string
if (nlast == ':') { // if need to round further
strp.replace(strp.end() - 1 - ipos, strp.end() - ipos, 1, nlast);
clast = '0'; // keep current char value
roundstr(strp);
} else {
strp.replace(strp.end() - 1 - ipos, strp.end() - ipos, 1, nlast);
if(clast==':') clast = '0';
}
}
sl = strp.length();
if (nlast == ':') {
if (ipos == 1) {
strp += '.';
} else {
strp += '0';
}
} else if (nlast=='.' && strp[sl-1] != '.') {
strp += '.';
} else {
if (ipos == 1 && strp[sl-1]!='.') {
strp += '.';
} else {
strp += clast;
}
}
return;
}
你这样称呼它:
#include <string>
#include <iostream>
#include <iterator>
#include <stdlib.h>
void roundstr(std::string&);
int main(int argc, char* argv[]) {
int p;
std::string strp;
switch (argc) {
case 2:
p = 2;
break;
case 3:
p = atoi(argv[2]);
strp = argv[1];
break;
default:
return 1;
break;
}
std::cout << strp << " " << p << std::endl;
roundstr(strp);
strp.erase(strp.end()-p, strp.end());
std::cout << strp << std::endl;
return 0;
}
如您所见,您必须处理删除多余的数字,但编写包装函数甚至是在构造过程中自动执行此操作的类并不难。
如果使用 c-strings 而不是std::string
. 如果您打算执行繁重的符号运算,我建议您替换 allstd::string
和char
withchar *
但在删除添加值时应该更加小心。
在字符串中找到点。然后,找到该位置之后的第四个字符。返回子字符串从0到点+3的位置,然后调整最后一个字符-如果原始字符串中点之后的第四个字符大于或等于5,则增加最后一个字符(或设置为'0',如果'9 ' 并增加 prievous 等等)。如果它小于 5 - 什么都不做,只返回原始字符串的子字符串。
虽然,我认为如果您只是将其转换为浮点数,它不会影响性能,但请使用(例如)boost::format
使其四舍五入。
这首先将其转换为浮点数。
int main()
{
std::string f = "12345.567675";
std::ostringstream ss;
float x = boost::lexical_cast<float>(f);
ss << std::fixed << std::setprecision(3);
ss << x;
std::string s = ss.str();
std::cout << s << "\n";
return 0;
}
结果如下:
./a.out
12345.567
假设你总是有一个点,后面至少有 3 个数字:
char *str = "12345.567675";
char *p = str;
while ( *p != '.' )
{
printf( "%c", *p++ );
// find a dot
}
for ( int i = 0; i < 4; i++ )
{
printf( "%c", *p++ );
}