| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 2165 人关注过本帖
标题:自己实现float/double转字符串问题
只看楼主 加入收藏
Escapist
Rank: 1
等 级:新手上路
帖 子:25
专家分:0
注 册:2020-4-27
结帖率:75%
收藏
已结贴  问题点数:10 回复次数:11 
自己实现float/double转字符串问题
自己写了一个double/float转字符串的函数,EspString是我自己写的一个动态字符串类,可以理解为MFC的CString
代码
程序代码:
    static void ToString(double DoubleValue, EspString& StringValue)
    {
        StringValue.Empty();
        if (DoubleValue == 0.0)
        {
            StringValue.Append('0');
            return;
        }
        bool IsNeg = DoubleValue < 0;
        if (IsNeg)DoubleValue = -DoubleValue;
        while (DoubleValue >= 1)
        {
            StringValue.Append(((int)DoubleValue % 10) + 48);
            DoubleValue /= 10;
        }
        if (IsNeg)
            StringValue.Append('-');
        StringValue.Reverse();
        if (DoubleValue == 0.0)
            return;
        StringValue.Append('.');
        while (DoubleValue != 0)
        {
            DoubleValue *= 10;
            StringValue.Append(((int)(DoubleValue) % 10) + 48);
        }
    }

但是启动了之后没有任何反应,而且过了很长时间报错——0x7646A6F2 处(位于 ***.exe 中)有未经处理的异常: Microsoft C++ 异常: char,位于内存位置 0x0118FE88 处。
请问到底是怎么回事呢?有什么方式来避免呢?谢谢各位大佬~~
搜索更多相关主题的帖子: float double return 字符串 Append 
2021-07-05 21:30
Escapist
Rank: 1
等 级:新手上路
帖 子:25
专家分:0
注 册:2020-4-27
收藏
得分:0 
Empty——清空字符串,等同于memset(Buffer,0,StrLen)(Buffer和StrLen是内部的变量)
Append——在后加字符/字符串,会监测Buffer大小,可自动拓展
2021-07-05 21:32
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:4 
其它的不谈,你说运行报错,那你总得告诉别人你传什么值给ToString了吧?否则别人怎么测试你这段代码?

你可以先将 EspString 替换为 CStringA 或 std::string,看看还错不错。没错的话,就是 EspString 的bug了。

当然,你的这段代码里全是逻辑错误
if (IsNeg) ------ 不小于0就一定是负数?inf/nan等等你全不考虑,+0.0 和 -0.0 估计你都没听说过
(int)DoubleValue ------ 浮点值一定可以转化为整型值?
DoubleValue /= 10 ------ 更想当然了,你这个操作一定不会改变原先处理过的位?
DoubleValue *= 10 ------ 同上
while (DoubleValue != 0) ------ DoubleValue有一丝可能是0吗?
即使你以上的错误全处理掉,那么 ab.cd 也是被处理成 "ab.abcd"
2021-07-06 09:12
我善治鬼
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:107
专家分:181
注 册:2015-2-16
收藏
得分:4 
同意楼上的, printf() 函数 都不会用还学什么C语言
2021-07-06 10:09
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:0 
printf 并不要求精确输出,gcc等是精确输出的,而VC就不是

想达成可移植性的话,可以用C++的 std::format 库(题主的代码是C++代码
所有的说明解释都放在了代码中
程序代码:
#include <iostream>
#include <format>
#include <cmath>
using namespace std;

int main( void )
{
    cout << format("{}",+0.0) << endl;
    cout << format("{}",-0.0) << endl; // 输出 -0
    cout << format("{}",NAN) << endl;
    cout << format("{}",INFINITY) << endl;
    cout << format("{}",DBL_MIN) << endl;
    cout << format("{}",DBL_MAX) << endl;

    cout << format("{}",12.34567890123456789) << endl;
    // 输出 12.345678901234567
    // 因为 12.345678901234567 是最短的可表示 12.34567890123456789 的数
    // 也就是在计算机眼中 12.345678901234567 和 12.34567890123456789 是同一个数,再多的位没意义

    cout << format("{:.100}",12.34567890123456789) << endl;
    // 输出 12.345678901234567348410564591176807880401611328125
    // 因为计算机就是用 12.345678901234567348410564591176807880401611328125 来表达 12.34567890123456789

    // 以上是两个比较有用的概念,如果你听不懂,我来打个比方
    // A要求B保存一个数
    // A报“12.34567890123456789……”,B说停停,报到“12.345678901234567”就可以了,我的精度就只有这么多,你报再多也只是浪费口水
    // A说“那你就是保存了12.345678901234567吗?”,B回答“不,我保存的是12.345678901234567348410564591176807880401611328125”
    // 之所以出现这种情况,是因为 有限位的十进制数 未必能用 有限位的二进制 来表达

    cout << format("{:1025}",DBL_MIN) << endl;
    // 输出 2.2250738585072014e-308
    // 因为之前所过 std::format 用最短的可精确表达格式,但这个格式可能是科学计数法

    cout << format("{:.1022f}",DBL_MIN) << endl;
    // 强制不用科学计数法,才能输出 0.00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002225073858507201383090232717332404064219215980462331830553327416887204434813918195854283159012511020564067339731035811005152434161553460108856012385377718821130777993532002330479610147442583636071921565046942503734208375250806650616658158948720491179968591639648500635908770118304874799780887753749949451580451605050915399856582470818645113537935804992115981085766051992433352114352390148795699609591288891602992641511063466313393663477586513029371762047325631781485664350872122828637642044846811407613911477062801689853244110024161447421618567166150540154285084716752901903161322778896729707373123334086988983175067838846926092773977972858659654941091369095406136467568702398678315290680984617210924625396728515625
}


所以,如果你想输出 最短精确值,那直接用 "{}" 就行了;
如果你想输出 完整精确值,得指定足够长的有效位,然后再将尾部的零去掉。
2021-07-06 10:59
rjsp
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:528
帖 子:9007
专家分:53942
注 册:2011-1-18
收藏
得分:0 
对比一下 C语言 的做法

程序代码:
#include <stdio.h>
#include <float.h>

int main( void )
{
    printf( "%f\n", 12.34567890123456789 );
    // 输出 12.345679,但 12.345679 和 12.34567890123456789 并非同一个数
    // 要求 最短精确格式 的话,printf做不到,当然做不到“最短”事也不大
    
    printf( "%.100f\n", 12.34567890123456789 );
    // gcc 可以输出精确的 12.345678901234567348410564591176807880401611328125000……
    // VC 未必行。 之所以说“未必”,是因为老版本的VC肯定不行,新版本的VC用gcc作标准,会尽量保持与gcc一致
    // 当然,即使gcc/vc等所有编译器的库都能精确输出,C标准也没有保证这一点
    return 0;
}


总之,只要避开旧版本的VC,那用printf其实问题也不大
2021-07-06 11:15
我善治鬼
Rank: 5Rank: 5
等 级:贵宾
威 望:17
帖 子:107
专家分:181
注 册:2015-2-16
收藏
得分:0 
其实有必要使用精度这么高的浮点数吗? double最大也就就支持20位小数. 如果进行大浮点数计算你不也要实现大整数浮点数的 加减乘除 法的加大版运算? 如果不这样做, 和一个整数进行运行, 比如和一个10位数运行, 小数后面10位就全部丢失了, 要这么高精度的小数有意义吗?
2021-07-06 11:37
Escapist
Rank: 1
等 级:新手上路
帖 子:25
专家分:0
注 册:2020-4-27
收藏
得分:0 
回复 3楼 rjsp
看来我学的还是太少了啊,您能说的再详细,推荐一些视频或书籍吗?

这是我最基本的想实现的,后期肯定要加inf或者nan的,这个我知道......
不过我听说double没有填满的部分可能会有一些伪随机数什么的,不过不太清楚......

不过还是谢谢您了~
2021-07-06 17:22
Escapist
Rank: 1
等 级:新手上路
帖 子:25
专家分:0
注 册:2020-4-27
收藏
得分:0 
回复 4楼 我善治鬼
我没懂您的意思???
2021-07-06 17:22
Escapist
Rank: 1
等 级:新手上路
帖 子:25
专家分:0
注 册:2020-4-27
收藏
得分:0 
回复 3楼 rjsp
或者说您感觉什么样水平的人会犯这样的错呢?我也很想提高自己~
2021-07-06 17:27
快速回复:自己实现float/double转字符串问题
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.017698 second(s), 8 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved