如何在c++中对包含双值的字符串强制执行精度
how do i enforce precision on a string containing a double value in c++
示例输入字符串:
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字符串而不是std::string
,这也可能会更快。如果您计划进行重载符号运算,我建议用char *
替换所有std::string
和char
,但在删除和添加值时应更加小心。
在字符串中查找点。然后,找到该位置之后的第四个字符。将子字符串从0返回到点+3的位置,然后调整最后一个字符-如果原始字符串中点后的第四个字符大于或等于5,则递增最后一个字符串(或设置为"0",如果为"9",则递增prievus,依此类推)。如果小于5,则不执行任何操作,只返回原始字符串的子字符串。
尽管如此,我认为如果您只是将其转换为float,则不会影响性能,请使用(例如)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++ );
}
- 字符串强制转换为常量字符*
- 如何对模板类型强制执行常量
- C++:我可以在模板参数包中强制执行至少1个agment吗
- 将字符串强制转换为GUID并不能得到正确的结果
- C++ - 查找函数无法在子字符串上执行
- 编译器未强制执行返回协定
- 如何在 Linux 上强制执行矢量下标超出范围的调试断言
- 如何使用C++模板强制执行正式协议?
- 为什么在与静态库链接时强制执行 order(例如 source.cxx -lstatic)
- 当函数在 GCC 中没有任何返回时,如何强制执行错误?
- 一个人如何从代表函数的字符串中执行运行时执行C 代码
- 强制执行执行顺序
- 替换decorator模式以强制执行创建顺序
- 我可以强制执行标量类型通过 int{} 初始化为零吗?
- 如何在C++17中强制执行模板和模板模板参数之间的约束
- 如何在Boost::DateTime中强制执行严格的解析
- 强制执行C++语句顺序
- makefile是否可以在C++中强制执行依赖项限制
- 强制执行此模板的更好方法
- 如何在c++中对包含双值的字符串强制执行精度