http://www.phpfans.net/ask/quiz1/44371008768.html

vc中可以用 sprintf(str,"%f",f); 实现;
之前写过一个,浮点数转字符串类型时,需要一个变量,指定小数点后几位,也就是有效位。
一般情况下为6位,当前大部分编译环境都是这样的。

所以我的实现方式是
1:对浮点数取证,方法很简单把浮点数强制转化为整形。
2:把这个整形转化为字符串类型(可以使用itoa方法,当然也可以自己辗转/10取得)
3:把上面的得到的数放入字符数组中,在最后一位加上字符"."
4:使用浮点数减去上面得到的整数得到一个0.xxxx的浮点数
5:使用这个浮点数乘以10^6(有效位的方)得到一个浮点性
6:再次执行1,2步
7:把两次得到的字符串连接起来就可以

具体实现过程中,有几点需要注意
1:需要判断浮点数的正负关系,负数也是执行上述过程,只是在最后输出的字符串上加上"-"
2:在实现过程中第四部的减会损失部分误差,可以对原浮点数直接乘10^6减去 整数乘10^6得到数取整。

STL的具体实现中也是使用类似方法,关于这个问题,记得1年前和奶油狗争论过,可以参考那片贴子。
---------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------
小时候(不见得多小,吼吼)写过类似的一篇文章,发表在CSDN的专栏上。现在看起来简直粗陋无比,因此萌发了重写的念头。

众所周知,计算机中的所有数据都是以二进制表示的,浮点数也不例外。然而浮点数的二进制表示法却不像定点数那么简单了。

先澄清一个概念,浮点数并不一定等于小数,定点数也并不一定就是整数。所谓浮点数就是小数点在逻辑上是不固定的,而定点数只能表示小数点固定的数值,具用 浮点数或定点数表示某哪一种数要看用户赋予了这个数的意义是什么。

C++中的浮点数有6种,分别是:

float:单精度,32位   
unsigned float:单精度无符号,32位   
double:双精度,64位   
unsigned double:双精度无符号,64位   
long double:高双精度,80位   
unsigned long double:高双精度无符号,80位(嚯,应该是C++中最长的内置类型了吧!)

然而不同的编译器对它们的支持也略有不同,据我所知,很多编译器都没有按照IEEE规定的标准80位支持后两种浮点数的,大多数编译器将它们视为 double,或许还有极个别的编译器将它们视为128位?!对于128位的long double我也仅是听说过,没有求证,哪位高人知道这一细节烦劳告知。

下面我仅以float(带符号,单精度,32位)类型的浮点数说明C++中的浮点数是如何在内存中表示的。先讲一下基础知识,纯小数的二进制表示。(纯小 数就是没有整数部分的小数,讲给小学没好好学的人)

纯小数要想用二进制表示,必须先进行规格化,即化为 1.xxxxx * ( 2 ^ n ) 的形式(“^”代表乘方,2 ^ n表示2的n次方)。对于一个纯小数D,求n的公式如下:   
n = 1 + log2(D); // 纯小数求得的n必为负数   
再用 D / ( 2 ^ n ) 就可以得到规格化后的小数了。接下来就是十进制到二进制的转化问题,为了更好的理解,先来看一下10进制的纯小数是怎么表示的,假设有纯小数D,它小数点 后的每一位数字按顺序形成一个集合:   
{k1, k2, k3, ... , kn}   
那么D又可以这样表示:   
D = k1 / (10 ^ 1 ) + k2 / (10 ^ 2 ) + k3 / (10 ^ 3 ) + ... + kn / (10 ^ n )   
推广到二进制中,纯小数的表示法即为:   
D = b1 / (2 ^ 1 ) + b2 / (2 ^ 2 ) + b3 / (2 ^ 3 ) + ... + bn / (2 ^ n )   
现在问题就是怎样求得b1, b2, b3,……,bn。算法描述起来比较复杂,还是用数字来说话吧。声明一下,1 / ( 2 ^ n )这个数比较特殊,我称之为位阶值。   
例如0.456,第1位,0.456小于位阶值0.5故为0;第2位,0.456大于位阶值0.25,该位为1,并将0.45减去0.25得0.206进 下一位;第3位,0.206大于位阶值0.125,该位为1,并将0.206减去0.125得0.081进下一位;第4位,0.081大于0.0625, 为1,并将0.081减去0.0625得0.0185进下一位;第5位0.0185小于0.03125……   
最后把计算得到的足够多的1和0按位顺序组合起来,就得到了一个比较精确的用二进制表示的纯小数了,同时精度问题也就由此产生,许多数都是无法在有限的n 内完全精确的表示出来的,我们只能利用更大的n值来更精确的表示这个数,这就是为什么在许多领域,程序员都更喜欢用double而不是float。

float的内存结构,我用一个带位域的结构体描述如下:   
struct MYFLOAT   
{   
bool bSign : 1; // 符号,表示正负,1位   
char cExponent : 8; // 指数,8位   
unsigned long ulMantissa : 23; // 尾数,23位   
};

符号就不用多说了,1表示负,0表示正   
指数是以2为底的,范围是 -128 到 127,实际数据中的指数是原始指数加上127得到的,如果超过了127,则从-128开始计,其行为和X86架构的CPU处理加减法的溢出是一样的。比 如:127 + 2 = -127;127 - 2 = 127   
尾数都省去了第1位的1,所以在还原时要先在第一位加上1。它可能包含整数和纯小数两部分,也可能只包含其中一部分,视数字大小而定。对于带有整数部分的 浮点数,其整数的表示法有两种,当整数大于十进制的16777215时使用的是科学计数法,如果小于或等于则直接采用一般的二进制表示法。科学计数法和小 数的表示法是一样的。   
小数部分则是直接使用科学计数法,但形式不是X * ( 10 ^ n ),而是X * ( 2 ^ n )。拆开来看。

0 00000000 0000000000000000000000   
符号位 指数位 尾数位

下面是一个分析float类型内存数据的程序,经测试是完好的,如果发现有问题,请提出来,我好改进。

#include <iostream>   
#include <iomanip>   
using namespace std;

int _tmain( int argc, _TCHAR* argv[] )   
{   
// 有符号的32位float类型浮点数变量的定义及数据初始化,其值可任意修改   
float fDigital = 0.0f;   
// 临时变量,用于存储浮点数的内存数据   
unsigned long nMem;   
// 将内存按位复制到临时变中,以便取用。   
nMem = *(unsigned long*)&fDigital;

// 以小数点后保留8个小数点的精度输出原始浮点数   
cout << setprecision( 8 );   
cout << "浮点数:" << fDigital << endl;   
cout << "-----------------------" << endl;

// 判断是否为0,全部位都为0的浮点数据表示0,无分析意义   
if ( nMem != 0 )   
{   
// 打印出其符号。   
// 最高1位为符号位。用bool来表示,true表示负数,false表示正数。   
// 和最高位为1的数据0x80000000进行按位与,可得到其符号。   
bool bNegative = ( ( nMem & 0x80000000L ) != 0 );   
// 如果是负数,则输入负号,否则输出空格。   
cout << "符号:" << ( bNegative ? '-' : '+' ) << endl;

// 打印出其指数。   
// 第30 - 23位是指数位,是有正负的8位整数数据,用char来表示。   
// 将内存右移一位,再左移24位,再硬性截断为8位即可得到指数原始数据。   
char cExponent = (char)( ( nMem << 1 ) >> 24 );   
// IEEE浮点数表示法规定,原指数加127为内存中的指数。   
// 将原始指数数据减127得到其真实指数(CPU会自动处理上下界溢出)。   
cExponent -= 127;   
// 以10进制带符号整数方式输出指数数据   
cout << "指数:" << (int)cExponent << endl;

// 打印出其尾数。   
// 第22 - 0位是尾数位,由于省去了头一位1,因此应该是24位无符号数据。   
// 用无符号长整型来表示。   
// 和最低22位都是1的数据0x7FFFFF进行按位与,可得到尾数原始数据   
unsigned long ulMantissa = ( nMem & 0x7FFFFFL );   
// 和第23位是1的数据0x800000进行按位或,可补齐省去的最高位1   
ulMantissa |= 0x800000L;   
// 以16进制整数方式输出尾数数据   
cout << "尾数:0x" << setbase( 16 ) << setfill( '0' ) << setw( 8 );   
cout << setiosflags( ios_base::uppercase ) << ulMantissa << endl;

// 完全基于整型算法来实现二进制小数到整数的转换极其复杂,   
// 这里借用double简单实现,仅说明其理论。详细算法见说明。   
// 计算出浮点数的整数部分,用双精度型表示   
double dInteger = 0;   
// 指数大于或等于0就代表尾数中存在整数部分   
if ( cExponent >= 0 )   
{   
// 如果指数大于23,则说明整数部分以科学计数法表示   
if ( cExponent > 23 )   
{   
// dCurBit用来计算和存储循环中对于每一位的位阶数   
double dCurBit = 1.0;   
// 循环所有位,计算科学计数法中的小数的十进制形式   
for ( int nBitIdx = 0; nBitIdx < 24; nBitIdx++ )   
{   
// 将整数部分左移当前位加9,将当前位置于最高位;   
// 再右移31位可得当前位,再用当前位阶乘以该位,   
// 即得累加数。累加计入二进制小数。   
dInteger += dCurBit * ( ( ulMantissa <<   
( 8 + nBitIdx ) ) >> 31 );   
// 由当前位阶除以2得到下次位阶。   
dCurBit /= 2;   
}   
// 将二进制表示的科学计数法转换为10进制   
dInteger *= pow( 2.0, (double)cExponent );   
}   
else   
{   
// 将尾数右移小数部分的长度,即可得到整数部分   
int nRightShift = 0;   
// 如果指数小于23,则说明存在小数部分,需要右移   
if ( cExponent < 23 )   
{   
// 尾数的原始长度减去指数即为小数部分长度   
nRightShift = 23 - cExponent;   
}   
// 将尾数数据右移小数部分的长度,可得到整数部分。   
dInteger = (double)( ulMantissa >> nRightShift );   
}   
}   
// 以10进制无符号整数方式输出整数部分   
cout << "整数部分:" << setbase( 10 ) << setprecision( 8 );   
cout << dInteger << endl;

// 计算出浮点数的小数部分,用无符号长整型表示   
double dDecimal = 0;   
// 如果指数小于23,则尾数中含小数部分   
if ( cExponent < 23 )   
{   
// 指数与23的差就是小数部分的长度,详见整数部分的处理。   
// 将所有位均为1的32位整数右移32减小数部分长度,即指数加9,   
// 可得到用于取得小数部分的mask数。   
unsigned long ulDecimalMask = 0xFFFFFFFF;   
// 如果指数大于或等于0就代表尾数中存在整数部分   
if ( cExponent >= 0 )   
{   
ulDecimalMask >>= ( 9 + cExponent );   
}   
else   
{   
// 如果是纯小数,则必须恢复规格化时删掉的整数1   
dDecimal = 1.0;   
}   
// 将尾数和mask数进行按位与,可得到小数部分   
// 二进制小数用无符号长整型表示   
unsigned long ulDecimal = ulMantissa & ulDecimalMask;   
// dCurBit用来计算和存储循环中对于每一位的位阶数   
double dCurBit = 0.5;   
// 循环所有位,计算科学计数法中的小数的十进制形式   
for ( int nBitIdx = 1; nBitIdx < 24; nBitIdx++ )   
{   
// 将二进制小数左移当前位加9,将当前位置于最高位;   
// 再右移31位可得当前位。   
// 用dCurBit乘以当前位,即得累加数。累加计入dDecimal。   
dDecimal += dCurBit * ( ( ulDecimal <<   
( 8 + nBitIdx ) ) >> 31 );   
// 由当前位阶除以2得到下次位阶。   
dCurBit /= 2;   
}   
// 将二进制表示的科学计数法转换为10进制   
dDecimal *= pow( 2.0, (double)cExponent );   
}   
// 以10进制无符号整数方式输出小数部分   
cout << "小数部分:" << setbase( 10 ) << setprecision( 8 );   
cout << dDecimal << endl;   
}   
else   
{   
cout << "浮点数为0,无分析意义" << endl;   
}

cout << "-----------------------" << endl;   
cout << "分析完毕,程序退出。" << endl << endl;

不可改动//   
system( "pause" );   
// _CrtDumpMemoryLeaks();   
return 0;   
不可改动//

}

double浮点数转字符串算法相关推荐

  1. c语言如何浮点数转换为字符串,C语言把浮点数转换为字符串

    1.把float/double格式化输出到字符串 标准的C语言提供了atof函数把字符串转double,但是没有提供把float/double转换为字符串的库函数,而是采用sprintf和snprin ...

  2. 不使用C/C++标准库实现的浮点数与字符串相互转换(最给力)

    C/C++标准库由于需要具有良好的通用性与全面性,使用了较为复杂的实现方法,实现的代码庞大 对于简单的Windows程序,使用C/C++标准库生成的EXE文件体积较大,整个程序80%以上代码可能均来源 ...

  3. MFC编程 -- 浮点数与字符串之间转换

    一.重新涉及界面 二.编写代码 if (nID == IDC_JISUAN2){TCHAR str[15];GetDlgItemText(hWnd,IDC_EDIT4,str, _countof(st ...

  4. python判断一个数是整数、浮点数还是字符串

    python判断一个数是整数.浮点数还是字符串 示例代码:

  5. 把浮点数转为字符串(隐形把数据进行四舍五入)

    #include <stdio.h> #include <stdint.h> int main(void) {     float floatData = 3.14159265 ...

  6. C语言sprintf函数(发送格式化输出到 str 所指向的字符串)(format 标签属性)(字符串拼接)(数字转字符串、浮点数转字符串)

    C语言函数 snprintf()(发送有限字符格式化输出到 str 所指向的字符串)(字符串拼接) 文章目录 描述 声明 参数 返回值 实例 20220124 上面的实例太简陋了,我们拓展一下 实例1 ...

  7. JavaScript实现floatAsBinaryString浮点转为二进制字符串算法(附完整源码)

    JavaScript实现floatAsBinaryString浮点转为二进制字符串算法(附完整源码) floatAsBinaryString.js完整源代码 floatAsBinaryString.j ...

  8. python字符串转浮点数_Python | 打印不同的值(整数,浮点数,字符串,布尔值)...

    python字符串转浮点数 In the given example, we are printing different values like integer, float, string and ...

  9. c# 浮点数十六进制字符串_从C#中包含十六进制值的字符串数组中打印整数值...

    c# 浮点数十六进制字符串 将十六进制字符串数组转换为整数 (Converting array of hexadecimal strings to integers) Let suppose you ...

最新文章

  1. python读取本地文件-python解析本地HTML文件
  2. 利用.net4.0的dynamic特性制造的超级简单的微信SDK
  3. C++ Primer 5th笔记(chap 12 动态内存)allocator类
  4. 互掐!美团“抛弃”支付宝,背后的真相到底是啥?
  5. 机器学习算法中的准确率、精确率、召回率和F值
  6. mysql maria引擎_MySQL/MariaDB---查询缓存与存储引擎
  7. java poi设置单元格格式为数值_Excel 文本转数值的方法——我找的好苦啊
  8. 马化腾:互联网企业竞争要注重什么
  9. 随机信号分析基础——例题篇(例题3.1)
  10. C++最简单的日期计算
  11. 《以太坊攻略》,小白如何逆袭成为技术大咖?要学的全在这里了
  12. MIT6.828学习之homework2:shell
  13. Android 打包解析软件包时出现问题
  14. mysql三m架构为什么_AnalyticDB for MySQL 3.0 技术架构解析
  15. 详解机器学习中的熵、条件熵、相对熵、交叉熵
  16. JS获取当前年的第一天/昨天/今天
  17. 场内交易基金实时数据 API 数据接口
  18. 快递代取项目——结构化需求分析与建模
  19. [转]一个男人该有的气质 (马云原话),二十几岁女孩该有的内涵(杨澜)。
  20. optimized_model_str = C.optimize(model_str, passes) IndexError: _Map_base::at

热门文章

  1. 5分钟搞定 微信早安推送 升级版
  2. 解决no session问题的三种方式
  3. Firefox OS 架构简析——(1)
  4. C# 设置文件默认打开程序
  5. Kubernetes原生api部署微服务5-监听Pod
  6. watch监听的几个方法
  7. JS纯前端实现文件保存
  8. htpp-server开启https服务终端报错问题
  9. 杭州的旅游景点有哪些传说的民间故事
  10. linux 复制 u盘 只读,Linux_ubuntu系统下向U盘拷贝数据提示目标是只读的,在ubuntu11.04下使用U盘的时候, - phpStudy...