double变量转换成字符串

niccctvcom 2006-12-06 05:01:38
一小段很简单的代码:
char tmp[17] = "";
double aaa;
aaa = 9999999999999997.0;
_gcvt(aaa, 16, tmp);
cout<<tmp<<endl;

调试过程中发现,执行完对变量aaa的赋值语句后,
只要aaa的整数部分位数超过16位或者等于16位但第一位为9时
aaa的值并不是我想要的
按道理,并没有超出double的取值范围
为什么会这样呢
都要被搞糊涂了,请教各位,谢谢
...全文
319 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
eqxu 2006-12-22
  • 打赏
  • 举报
回复
double:双精度,64位
struct MyDouble
{
bool bSign : 1; // 符号,表示正负,1位
short cExponent : 11; // 指数,11位
unsigned long ulMantissa : 52; // 尾数,52位
};

他的存在形式为 内存的存在hex dec
double myd = 1.1;//0x3ff199999999999a 1.1000000000000001
0011 1111 1111 0001 1001 ... 1010
double myd1=-1.1;//0xbff199999999999a -1.1000000000000001
1011 1111 1111 0001 1001 ... 1010

节码 011 1111 1111 代表E=1023 这个代表是后面的尾数要乘以2^(E-1023)=1

所以你说的函数可以通过这种为运算的方式来得到字符串
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
说错了,实际中aaa的值来源于数据库中的decimal(16,0)字段
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
明白,关键现在精度并没有超出double的范围
我只是想说在精度和取值范围两方面都不会超出而已
taodm 2006-12-06
  • 打赏
  • 举报
回复
取值范围和精度是2个不同的概念。
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
其实关于它的精度我注意到了,实际中aaa的值来源于数据库中的decimal(17,0)字段,我想并没有超出double规定的精度范围,而且最大的值也只到16位9,也不会超出double的取值范围
taodm 2006-12-06
  • 打赏
  • 举报
回复
说得很清楚了,double就这么多精度。
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
另外,在转换的过程中,如果_gcvt(aaa, 16, tmp)中的第二个参数小于aaa整数部分的位数,它是会自动进行四舍五入的,但问题是,现在的第二个参数正好等于整数位数。
而且,如果aaa的整数部超过16位(或等于16位且最高位是9),即便第二个参数等于或大于整数位数,也会得不到想要的值。
说起来很罗嗦,给些实验结果:(总保证第二个参数等于整数位数)
aaa = 89988999999999967.0;//17位整数
输出:89988999999999968 //错误
aaa = 9998899999999997.0;//16位整数,最高位是9
输出:9998899999999996 //错误
aaa = 8998899999999997.0;//16位整数,最高位不是9
输出:8998899999999997 //正确
真是不理解了,求助阿
jixingzhong 2006-12-06
  • 打赏
  • 举报
回复
也就是说, 你的代码完全没有问题!

解决的办法,
比较简单的是使用 更高精度的数据类型,
比如 long double ,
它需要 C99 标准的支持 ...

这种方法还是有限制,
但是至少可以暂时解决问题~

如果 long double 还是不够 ,
那么,
字节写一个 高精度处理 浮点数据类吧, 呵呵
taodm 2006-12-06
  • 打赏
  • 举报
回复
你期望得到什么?
浮点没有绝对精确值,得到9999999999999996已经是算完全正确了。
到在本论坛找IEEE符点表示法的帖子看吧。
sans 2006-12-06
  • 打赏
  • 举报
回复
sprintf( tmp, "%.1f", aaa );
jixingzhong 2006-12-06
  • 打赏
  • 举报
回复
这个没有办法,
因为 double 的精度限制了就是 15-17 位,
如果多余这个位数,
后面的就是 一些随机值, 是无效的
taodm 2006-12-06
  • 打赏
  • 举报
回复
那就别用_gcvt。
sprintf是完全可移植代码,_gcvt不是。
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
和缓存大小也没什么必然联系
况且我在转换时已经指定了存储16位数字,正好是整数部分的位数
而且不会超出缓存范围
niccctvcom 2006-12-06
  • 打赏
  • 举报
回复
试过了,输出结果只是多了几位小数
如下:9999999999999996.000000
(当aaa = 9999999999999997.0;)
郁闷!
taodm 2006-12-06
  • 打赏
  • 举报
回复
另外,17恐怕太小了,先开个128。
taodm 2006-12-06
  • 打赏
  • 举报
回复
用sprintf试一下。

64,676

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧