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币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!
其他相关推荐
JS小数运算出现多位小数的问题
写在前面的话: 今天帮同事解决了一个问题,就是小数相乘出现很多位小数的问题;这个问题自己以前也遇到过,现在特意来总结一下; Number类型: Number类型是ECMAScript中最常用和最令人关注的类型了;这种类型使用IEEE754格式来表示整数和浮点数值(浮点数值在某些语言中也被成为双精度数值),为支持各种数据类型,ECMA-262定义了不同的数值面量格式。 十进制: var
造成 js 浮点数计算出现多位小数情况的原因和解决办法
     最近在项目当中遇到了浮点数计算有一些特殊情况会出现很多位小数,自己总结了一下,并封装了一个解决此问题的方法。一、浮点数计算的几种特殊情况     0.1+0.2 = 0.30000000000000004      10.22*100 = 1022.0000000000001     2.4/0.8 = 2.9999999999999996     32.2*100 = 3220.000...
Javascript计算浮点数乘积出现多位小数解决方案
Javascript在进行浮点数的乘积运算,会出现多位小数的情况。 这是由于在运算的时候先把浮点数转化成二进制后进行运算,但是有的小数在二进制编码后出现无限循环,因而导致计算出现了误差,在其它变成语言中也有类似的问题。 原因解释参考自百度知道: 例如:求1038.1-1000 1038.1=10000001110.00011001
处理mysql金额运算sum*float出现多位不精确小数
通过 sum binary 指定float 字段 来获取 字段数据之和
js中小数相加小数点后面多出很多位
今天在页面上用到了js进行小数相加119.01+0.01,结果大家都知道应该是:119.02的,然而结果是119..0200000…. ,莫名其妙的,还以为是我写的程序有问题,后来查了下才知道这是javascript浮点运算的一个bug. 解决办法: 使用toFixed(2)函数把结果保留小数点后两位!Author:leedaning 本文地址:http://blog.csdn.net/lee
javascript关于小数计算的结果会出现小数的位数变多的现象
javascript关于小数计算的Bug,出现结果小数位数变多的现象
JavaScript 运算出现多位小数的解决办法
JavaScript小数运算出现多位的解决办法 在开发JS过程中,会经常遇到两个小数相运算的情况,但是运算结果却与预期不同,调试一下发现计算结果竟然有那么长一串尾巴。 先看几个例子,在Chrome控制台测试结果如下: 产生原因: JavaScript对小数运算会先转成二进制,运算完毕再转回十进制,过程中会有丢失,不过不是所有的小数间运算会有这个问题。 解决办法: ...
js计算出现多位小数-Javascript 浮点运算问题分析与解决
分析 JavaScript 只有一种数字类型 Number ,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的。 浮点数的精度问题不是JavaScript特有的,因为有些小数以二进制表示位数是无穷的:十进制 二进制 0.1 0.0001 1001 1001 1001 … 0.2 0.0011 00
Mysql的float类型sum出现多位不精确小数
方法一:最好的办法是将float字段改为decimal(16,6)。    方法二:使用binary关键字解决。具体操作为“select sum(binary 字段名(float类型))”     SELECT  SUM(BINARY(sign.order_amount))  AS phone_signup_amount, FROM `t_newsky_sign_up_wx` `sign` ...
python-正确保留多位小数
python自带的float函数在保留两位小数的时候不够准确容易出现误差,而(‘%.2f’ % a)的方式是将数字转成了字符串类型,无法进行数字运算,所以这里我们将封装一个方法来实现正确的保留多位小数。 1234567891011121314 from functools import reducedef str2float(strf): def char2n