• 原文地址:https://www.cnblogs.com/finallyliuyu/p/1810071.html

c++中double转换成string型(浮点数的格式化)(转)

 

在日常编程中--包括对话框、关系数据库、金融程序、SMS程序及一切处理数据文件的程序,需要控制小数点后的小数位的情况非常普遍,本文中将要讲 解如何用简单的方法来控制小数位,另外,还要揭开字符串及数据精度的一点点小秘密。

问题的引出

如有一个函数,其可接受一个long double参数,并将参数转换为字符串,结果字符串应保留两位小数,例如,浮点值123.45678应该生成“123.45”这样的字符串。表面上看来 这是一个意义不大的编程问题,然而,如果真要在实际中派上用场,函数应设计为具有一定弹性,以允许调用者指定小数位数。另外,函数也应该能够处理各种异常 情况,如像123.0或123这样的整数。

在开始之前,先看一下编写“优雅”C++代码时的两句“真言”:

“真言”1:无论何时需要格式化一个数值,都应先转换为一个字符串。这样可保证每位数刚好占据一个字符。

“真言”2:在需要转换为字符串时,请使用库。

转换函数的接口非常简洁:第一个参数是需被格式化的数值;第二个参数代表小数点后显示的小数位,且应该具有一个默认值;返回值为一个string类 型:

string do_fraction(long double value, int decplaces=3);

注意,第二个参数代表的小数位数中包括了小数点,因此,两位小数需要默认值为3。

精度问题

当然,第一步是把long double值转换为一个string,使用标准C++库简直是手到擒来。然而,有一件事情必须引起注意,因为某些原 因,stringstream对象默认精度为6,而许多程序员错误地把“精度”理解为小数的位数,这是不正确的,精度应指代全部位数。因而,数字 1234.56可安全地通过默认精度6来表示,但12345.67会被截断为12345.6。这样的话,如果你有一个非常大的数,如1234567.8, 它的结果会静悄悄地转换为科学记数法:1.23457e+06,这显然不是我们想要的。为避免这样的麻烦,在开始转换之前,应把默认精度设为最大。
为 得到long double能表示的最大位数,可使用库:

string do_fraction(long double value, int decplaces=3)
{
int prec=numeric_limits::digits10; // 18
ostringstream out;
out.precision(prec);//覆盖默认精度
out<<value;
string str= out.str(); //从流中取出字符串 数值现在存储在str中,等待格式化。

小数点的位置

要进行格式化,首先要确定小数点的位置,如果小数位多于decplaces,do_fraction()会删除多余的。

要定位小数位,可使用string::find(),在STL算法中使用了一个常量来代表“数值未找到”,在字符串中,这个常量为 string::npos:

char DECIMAL_POINT='.'; // 欧洲用法为','

size_t n=str.find(DECIMAL_POINT);
if ((n!=string::npos)//是否有小数点呢?
{
//检查小数的位数
}

如果没有小数点,函数直接返回字符串,否则,函数将继续检查小数位是否多于decplaces。如果是,小数部分将会被截断:

size_t n=str.find(DECIMAL_POINT);
if ((n!=string::npos)//有小数点吗?
&&(str.size()> n+decplaces)) //后面至少还有decplaces位吗?

//在小数decplaces位之后写入nul
str[n+decplaces]='\0';

最后一行覆盖了多余的小数位,它使用了\0常量来截断字符串,要注意,string对象的数据可以包含nul字符;而字符串的实际长度由 size()的返回值决定。因此,你不能假定字符串已被正确地格式化,换句话来说,如果在str中原来为“123.4567”,在插入\0常量之后,它变 成了“123.45\07”,为把str缩减为“123.45”,一般可使用自交换的方法:

str.swap(string(str.c_str()) );//删除nul之后的多余字符

那它的原理是什么呢?函数string::c_str()返回一个const char *代表此字符串对象,而这个值被用作一个临时string对象的初始化值,接着,临时对象又被用作str.swap()的参数,swap()会把值 “123.45”赋给str。一些老一点的编译器不支持默认模板参数,可能不会让swap()通过编译,如果是这样的话,使用手工交换来代替:

string temp=str.c_str();
str=temp;

代码虽不是很“优美”,但能达到目的就行。以下是do_fraction()的完整代码:

string do_fraction(long double value, int decplaces=3)
{
 ostringstream out;
 int prec=
 numeric_limits::digits10; // 18

 out.precision(prec);//覆盖默认精度
 out<<value;
 string str= out.str(); //从流中取出字符串
 size_t n=str.find(DECIMAL_POINT);
 if ((n!=string::npos) //有小数点吗?
 && (str.size()> n+decplaces)) //后面至少还有decplaces位吗?
 {
  str[n+decplaces]='\0';//覆盖第一个多余的数
 }

 str.swap(string(str.c_str()));//删除nul之后的多余字符

 return str;
}

如果不想通过传值返回一个string对象,还可增加一个参数,把str对象以引用传递:

void do_fraction(long double value, string & str, int decplaces=3);

从个人的角度来讲,还是倾向于让编译器做这样的优化,另外,使用传值返回,还可以让你以下面这种方式使用do_fraction():

cout << funct(123456789.69999001) << '\t' << funct(12.011)<<endl;

输出:123456789.69 12.01

c++的double转string(转)的更多相关文章

  1. C++11中int,float,double与string的转化

    在C++11中可以使用std::to_string()函数将数值转换为string格式,十分方便. 以下部分来选自cplusplus.com. std::to_string string to_str ...

  2. arduino:int & double 转string 适合12864下使用

    转自:http://www.geek-workshop.com/forum.php?mod=viewthread&tid=3383&highlight=12864 很多人在玩的时候,都 ...

  3. swift中Double转String

    swift上手有好几天了.发现swift除了本身的几个基本类型转换,一些比较特殊的数值类型转换需要“桥接”到Objective-C来进行- 代码当然也很简单- var numString = &quo ...

  4. c++ 中double与string之间的转换,char *

    运行代码为 /* * main.cpp * * Created on: Apr 7, 2016 * Author: lizhen */ #include <iostream> //#inc ...

  5. C++ double转string类型以及MFC控件简单使用方法

    这两天项目须要,測试c++库里面内容.生成jar再给Android调用.我没有学过C++,如今開始记录C++简单使用方法.測试时候一般都是使用mfc程序来測试.要输入值.显示结果吗.我用的编译环境vs ...

  6. 【C++】int转string,double转string方法,string转int,string转double方法

    C++的格式比较多比较复杂,转换起来有很多方法,我这里只提供一种,仅供参考. int或double转string 使用字符串流的方式可以比较简单的完成转换 需要添加头文件 #include <s ...

  7. java Int类型转为double 类型;string转double

    int a=12; double b=(double)a; or double c=Double.valueOf((double)a); string a_s="12"; doub ...

  8. C#学习笔记-输入数据判断(int、double、string)

    代码: using System; using System.Windows.Forms; namespace CheckInput { public partial class Form1 : Fo ...

  9. 关于float /double、string类型的hash函数/hash表实现(转)

    #include <ext/hash_map> #include <math.h> #include <stdio.h> using namespace std; ...

  10. Double.parseDouble(String s)

    要把字符串转换为Double类型,只能转换“0.02”这种格式的字符串,不能转换百分比格式的,比如“2%” 这个时候可以Double cbl= Double.parseDouble(“2%”.repl ...

随机推荐

  1. 【转载】SQL SERVER 中单字节和双字节互转自定义函数(全角半角转换)

    一.首先创建一个自定义函数,代码如下: alter function f_convert( @str nvarchar(4000), --要转换的字符串 @flag bit --转换标志,0转换成半角 ...

  2. 如何使用 Blackbox Exporter 监控 URL?

    前言 监控域名和 URL 是可观察性的一个重要方面,主要用于诊断可用性问题.接下来会详细介绍如何使用 Blackbox Exporter 和 Prometheus 在 Kubernetes 中实现 U ...

  3. 一份前端够用的 Linux 命令

    前言 你好,我是悦创.我用 VuePress 搭建博客,又实现了 GitHub 和 Gitee Pages 的自动部署,但我最终还是决定自己建站,而在建站的过程中,必不可少会用到 Linux 命令,所 ...

  4. Creator 2.x 升级 3.x 基础 API 差异总结

    上一篇我们介绍了 Cocos Creator 2.x 项目升级 3.x 的大流程. 但最后一步,还需要手动将之前 2.x 写的函数注释一处处的放开. 并将 2.x 的代码写法改成 3.x 的,下面我们 ...

  5. 安装Ubuntu系统到中国移动电视盒子

    根据B站的视频资料,貌似这个盒子的性价比要比树莓派高一些,所以做了这个安装实验.新年伊始,armbian库也加紧升级,感觉大家都在想尽一切办法告别3年疫情给大家带来的伤害. B站视频推荐把系统安装在盒 ...

  6. threeJs构建3D世界

    threejs官网 https://threejs.org/docs/index.html#manual/zh/introduction/Installation (官网非常的详细) 导入安装 npm ...

  7. Python3+Selenium3自动化测试-(六)

    这里来说一说selenium中的等待方式,其实在webdriver只有两种类型等待方式,显式等待和隐式等待,之前是在程序运行过程中使用time模块中的sleep进行代码的休眠进行强制等待,是显式等待中 ...

  8. 带你熟悉3种AQS的线程并发工具的用法

    摘要:AQS 的全称为(AbstractQueuedSynchronizer),AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的大量的同步器. 本文分享自华为云社区 ...

  9. IDEA必备插件、阿里巴巴规范插件(代码格式化,注释模板化)的安装及使用和快捷键设置

    背景:记录下idea的配置,换电脑方便直接配置这些信息 第一步:安装必备插件如下 英文直接翻译就是插件的作用,大部分不用额外配置,Adapter for Eclipse Code Formatter是 ...

  10. 浅谈Python中的if,可能有你不知道的

    Python中的if,没那么简单,虽然也不难 https://docs.python.org/zh-cn/3.9/reference/compound_stmts.html#if python语言参考 ...