2 xwinterwinterwinterx XwinterwinterwinterX 于 2016.04.20 12:50 提问

浮点数输出很多位小数出现错误
 #include <iostream>
#include <cstdio>
using namespace std;
int main()
{
    char str[1000];
    sprintf(str,"%.100lf",(double)1/250);
    cout<<str;
}

运行这个程序得到的结果是
0.004000000000000000000000000000000中间有一段非零数字
00000000000000000000

11个回答

qq_34688538
qq_34688538   2016.04.20 12:57

图片说明

lxd2502
lxd2502   2016.04.20 13:04

浮点数在计算机中其实是一种不精确的表示,它的计算是一种实数的近似值计算,存在舍入(rounding)误差,不够精确,你这个输出结果是很正常的。

qq423399099
qq423399099   Ds   Rxr 2016.04.20 13:11

浮点数无法在计算机中精确存储,比如存0.004也只是存一个无限接近0.004的数
可能存成0.0040000000000001也可能是0.003999999999999
参考:http://www.cnblogs.com/dolphin0520/archive/2011/10/02/2198280.html

YXTS122
YXTS122   2016.04.20 13:20

把%.100lf改为%.100f试试 ,不写那个l

herozhangbz
herozhangbz   2016.04.20 14:50
herozhangbz
herozhangbz   2016.04.20 14:53

参考原文http://wenku.baidu.com/link?url=j8tNlNuV1xovu3jBR_DEdJ3o5amLsDgReUR8wcZhvUr1DT3_3q7qJ1yX7M_ZESRr-tZTMgZLl5sR2Fa-5OONfsCnw_eVVlWmXL-nidrRZju

你去百度下浮点数的存储格式。机器只能识别0,1,需要二进制转换成十进制。理论上,有限位数的二进制浮点数必能转换为有限位数的十进制数;但对于有限位数的十进制浮点数,转换为二进制数不能保证是有限位数,且多数情况下不是有限位数。因此,如果提供足够的输出位数,二进制浮点数可以精确转换为十进制数,不产生转换误差。但是,由于没有一个2n与lOm(n,m为整数)相等,二进制和十进制相互转换的位数没有简单的若干位对应若干位的对应关系。一般地,二进制浮点数向十进制转换都只提供若干位的近似值,并不提供全部的数字位数。事实上更主要的原因是:计算机中表示的二进制浮点数绝大多数本身就是实际数值的近似值,从有效数字的角度看,转换为十进制数时提供更多位数字并无使用价值。这里自然就有一个如何看待和精确使用数值的问题,即有效数字位数的问题。尤其对于各种数值计算,必须掌握其有效数字位数。但查阅有关资料,没有看到对计算机中浮点数的有效数字位数的准确叙述,一般仅指出fIoat和doubIe型大致的有效数字位数,且说法不一,没有给出依据。在此,从相对误差(误差绝对值与数值绝对值的比值)的角度给出一般性的结论。
http://ask.csdn.net/questions/248943

HOLY3KILL
HOLY3KILL   2016.04.20 16:11

大哥。。1/250不等于0.004等于什么?你str里面的值存的不就是1/250的值么?你真的是想问这个问题么?你是想输出0.000000000000000000000000?

HOLY3KILL
HOLY3KILL   2016.04.20 16:24

看错。请LZ无视我。。。。。

huanongying131
huanongying131   2016.04.20 17:11

首先编译器会把 (double) 1/25 转换成双精度浮点型

what is float-point format ? 一般 通用的编译器都会采用IEEE Standard 754标准 (such as 微软的编译器)

我们比较熟悉的有 单精度 (float 32bit) 双精度(double 64bit) 还有扩展精度( 80bit 比较少见, 所以不讨论) 不知你对变量的理解是怎样的 但在我的
眼里不管什么变量 都是 一字节 两字节 四字节 八字节的二进制码 所以我会以二进制码的形式讲解
注意:计算机只认识二进制 0和1 也就是低电平和高电平

float 总共有32位 0~22位是有效数字 23~30位是指阶码 第31位是符号位 从0开始数 到31 刚好32位 所以别再懊恼 我是sb吗 明明说32位 你却到31
double 总共有64位 0~51位是有效数字 52~62位是阶码 第63位是符号位
有效数字: 当然是有效的数字了 是不是 真不好解释 比如 1/3 =0.3333333333........ 我要保留两位有效数字 则1/3=0.33 呵呵
阶码:相似指数 但他是二进制的指数 而且在IEEE-754标准中需要加上一个特殊值 等等 你不必过分纠结 后面会详细的

符号位:就是数学里的正 负了 若该位为零 是正数 若该位为1 是负数
例如: 将十进制数100.25转换成单精度的格式的数(32位)
100.25 => 1100100.01
1100100.01 =>1.10010001*2^6 小数点的左边必须是1 而且是只有一个1 (人家规定的 不要问为什么)
正数 符号位:0
因为指数6(十进制)=110(二进制) 所以 阶码 : 110+01111111=10000101 为什么指数+特殊值 下面解释
有效数字:10010001000000000000000 (23位) 小数点左边的1哪去了呢 被隐藏了 iee规定二进制的
小数点左边必须是1 为什么这样规定啊 当然是为了扩大数字的取值范围啦 你想想如果在正常数值格式
转换成浮点格式时 把小数点的左边的1隐藏 在浮点格式转正常格式时 再加上这个1 我们就可以在32位的
空间中多加一位了
为什么阶码是 二进制的指数+01111111(32位 64位又不同) 我觉得是和能加速比较大小的速度 首先我们都是
1.xxxxxx 这样的格式 当我们的指数越大 值就越大 当指数是正数时 最高位肯定是0 所以加上这个值肯定最
高位的值为1 当指数是负数时 最高位肯定为1 所以加上这个值 最高位的值肯定就是0了 这样 就能通过比较
指数的大小来比较整个值了 只有当这两个指数值相等时 才比较有效数字 在加减运算 乘除运算应该也能起到
加速作用 当然了 也可能并没有什么加速作用 可能最大的原因是能简化硬件的设计 降低成本 这都是我猜的 因为
我也不是硬件设计的 但不管怎么做 都是有原因的 呵呵

只要按iee-745的规定就可以了 你可以百度一下

ok 大致的认识就讲的这里 我们来讨论你的问题吧 别说 你还不懂 我最讨厌了 你不懂 难道不会百度啊 最好google
(double)1/25 是双精度 是一个64位双精度值

首先将 1转换成双精度格式的二进制值 : 数值后面加D 表示十进制 加b表示二进制 加h表示十六进制
1d=1b

所以 符号位:0 阶码: 0b+01111111111b=01111111111b=3ffH(十六进制哦) 加01111111111b是双精度的 (iee规定的)
有效数字:0b
所以在内存中的值是 : 3ff0 0000 0000 0000h 用十六进制表示 64位的数
25转换成双精度的格式的二进制值:
25d=11001b=1.1001*2^4 b 你如果说我不知道怎么转换啊 我也没办法啊 我也是用计算器的 原理哪里都能找到
正数 符号位:0 阶码 4d+01111111111b=100b+01111111111b=10000000011b=403h
有效数字:1001b
所以在内存中的值是:4039 0000 0000 0000h

嗯 然后把这两个64位的值装入fpu的数据寄存器中 然后执行除操作
得到结果为 3fa4 7ae1 47ae 147b h (h是十六进制) 你迷茫了 或者在敬佩我 “大神啊" :> 哈哈哈哈
我也不是自己用纸和笔算出来的 我用的是编译器 反汇编出来的 当然了 编译器也是基于理论计算出来的 (通过fpu)
为什么是这个数 啊 i don't know 这关系到硬件方面的 东西

我们看看 3fa4 7ae1 47ae 147b h 是什么
符号位为0 所以是正数 3fah=011 1111 1010b 指数= 011 1111 1010b-011 1111 1111b=111 1111 1011b=-5
4 7ae1 47ae 147bh=0100 0111 1010 1110 0001 0100 0111 1010 1110 0001 0100 0111b
ok
最终二进制值为 0.0000 1010 0011 1101 0111 0000 1010 0011 1101 0111 0000 1010 00111b
即 2^(-5)+2^(-7)+2^(-11).......... 接近于 1/25

至于为什么 0.040000000中间有数字00000000 可能和 sprintf函数的转换有关 因为这是一个非常复杂的转换 只能近似 而不能一定准确
当然了 你真想知道答案 那就把sprintf函数的源代码看一遍吧

ice_candy
ice_candy   2016.05.01 18:15

ieee 754浮点数标准

共11条数据 1 尾页
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!