C语言, float double输出不一样,求大神

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言, float double输出不一样,求大神相关的知识,希望对你有一定的参考价值。

当然不一样啦,单精度(float),双精度(double)。
它们可以接收的实型常量的有效数字位数是不同的。
就是说,double型可以接收实型常量的16位的有效数字,但是float只能就收实型常量的7位有效数字,在有效数字后输出的数字都是不准确的。
参考技术A float

double
在输出的时候其实都是用%f输出。c语言中,浮点型输出默认都是输出小数后6位。你为什么会认为double会输出到小数后15位呢,我感觉你是认为double的精确度有15位,float的精确度是7位,对吧,其实事实double和float在输出的时候都是默认输出到小数后6位,但是你可以用%m.nf
的格式控制
参考技术B 首先我们要确定一点,计算机中的浮点数和整数一样,并不是我们在生活中用的10进制,这一点你可以参见IEEE754标准中的定义
http://baike.baidu.com/link?url=1uzF-ySHDP1FUmNTRMMPPH_WbE1RpRY_BZ_vkOlz2xOhhLfHfZntkd5u1avSdVVKrUw-C6_eNMUdOPTENVv1y_
(百度百科)
然后我们就知道,二进制的小数精度和十进制的小数精度在进行转换的时候是会有出入的
十进制里面,我们的精度是0.1,
0.01,
0.001,
....
二进制里面的精度则是1/2,
1/4,
1/8,
1/16,
......也就是0.5,
0.25,
0.125,
0.0625,
.....
自然在多数情况下不会出现按十进制的某一位截断的情况
参考技术C 很正常的嘛,浮点的存储是按照IEEE754标准的。简单的说它内部是2进制的,63.245
根本不可能用2进制的浮点精确表示,所以才会有很少的误差。这是正常的。

C语言中double类型怎么使用?

#include <stdio.h>
void main()

double a;
a=1.123456789;
printf("%f\n",a);

怎么不行呢?为什么还是一样输出6位小数?

使用printf时,它们具有相同的格式说明符,但使用scanf时,它们没有相同的格式说明符。

为什么是这样?因为printf的参数被提升,而scanf的参数(作为指针)却不被提升。

这种论点提升到底是什么?当较小尺寸的参数(特别是char,short和float)传递给可变参数函数(如printf之类的函数,其参数数量不固定)时,它们将转换为较大尺寸。Char和short转换为int,float转换为double。

为什么这样 据我所知,纯粹出于历史原因。C的设计师认为这是个好主意,因为这些转换基本上是免费的,因为所有类型的尺寸都足够小,可以放入单个寄存器或堆栈中的单个“单元”(将内容压入堆栈必须与某些字节边界对齐,例如,堆栈上的每个项目都必须以4的倍数的地址开头。同样,显然,这种转换减少了传递参数时的错误。

因此,当您向printf传递float类型的参数时,实际上它会在转换为printf之前就转换为double类型。我们可以使用调试器证明这一点。我写了下面的C代码:

主要功能编译成:

领取关于C/C++更多学习资料:

我在调用printf之前(在地址0x63b处)放了一个断点。根据Linux x86_64调用约定,浮点参数在XMM寄存器中传递(CPU中特殊的小内存位置,可用于对多条数据并行执行同一条指令,但实际上可用于大多数事情) 。因此,我查看了第一个XMM寄存器xmm0,然后:

xmm0中的值之一,当解释为双精度值时,是1,恰好是我们传递给printf的值。同时,当将该寄存器中的值解释为浮点数时,它们是这样(巧合的是,我们得到1.875)。因此,转换确实发生了。这就解释了为什么对于printf,我们在浮点数和双精度参数中都使用%f -浮点数无论如何都会转换为双精度,因此printf不能分辨出两者之间的区别。

同时,scanf的参数是指针,因此不受此转换的限制。其原因是因为所有指针类型仅包含内存地址,并且所有内存地址都具有相同的大小(在我的64位计算机上为64位)。因此,当scanf在其格式字符串中获得%f时,它将期望一个float *类型的指针,而当它获得%lf时,将期望得到double *类型的指针。如果格式说明符和指针的类型不匹配,则会产生一些有趣的结果。

由于float的大小为4个字节,而double的大小为8个字节(至少在我的机器上),因此当我们写入float *类型的指针所指向的位置时,我们将覆盖4个字节的内存。同时,如果我们写入由双*指向的位置,则将覆盖8个字节的内存。考虑以下代码:

printf说明符上的.15标志只是使printf精确度更高。由于我们使用的是双精度值(并且正如我刚刚说的那样,%f也适用于printf的双精度值),因此我们实际上可以访问具有这种精度的数字(只要它们不是太大而不能填充即可。我实际上不是对浮点表示非常了解)

编译并运行后,结果如下:

如您所见,如果我们忽略所有类型的fuckery,则数字应该匹配,但它们甚至不相近。这是为什么?

好吧,我们给scanf%f说明符,所以它期望一个浮点数*。但是我们传递了一个双*。现在,这些指针的实际值都只是地址-scanf不知道它们之间的区别。它进行了下去,读取我们输入的值,并将其存储为float 。但是浮点数仅占用4个字节,因此scanf只会在我们可用的double变量的8个字节中写入4个字节。在我的情况下,由于我的机器是低位字节序的,因此似乎对应于double变量的细粒度(小有效位)数字的第4个字节将被覆盖。因此,当我们打印出double double back时,我们得到的数字几乎与以前相同,但最低有效数字有所变化。

有想学习更多C/C++知识的,可以点击下方了解更多,领取免费学习资料:
参考技术A C++中你想建立一个变量的时候,需要告诉编译器变量的数据类型,以便编译器给变量分配存储空间。
格式:int i; 这是整型变量的声明格式。
如果要声明双精度型变量,也就是小数,相同道理
double i;
这样编译器就知道i是一个双精度小数变量。
另外 float也表示小数,是单精度小数。float和double的区别在于,float所允许的小数范围小,double允许的小数范围大
参考技术B double是C语言中的双精度浮点数类型,用来表示实数。

1 定义:
double var_name;
这样定义一个名字为var_name的double类型变量。

2 赋值:
var_name = 100.325;
同其它类型的赋值语句一样,对var_name赋值用=运算符,右侧可以是任意表达式。

3 输入:
scanf("%lf", &var_name);
%lf格式符号对应double,可以用来对double类型输入,以下输出类似。

4 输出:
printf("%lf", var_name);
参考技术C a中存的已经是double了,只不过是没有输出来而已你可以用
printf("%.9f\n",a);进行输出本回答被提问者采纳
参考技术D C++中你想建立一个变量的时候,需要告诉编译器变量的数据类型,以便编译器给变量分配存储空间。
格式:int i; 这是整型变量的声明格式。
如果要声明双精度型变量,也就是小数,相同道理
double i;
这样编译器就知道i是一个双精度小数变量。
另外 float也表示小数,是单精度小数。float和double的区别在于,float所允许的小数范围小,double允许的小数范围大。

以上是关于C语言, float double输出不一样,求大神的主要内容,如果未能解决你的问题,请参考以下文章

C语言 关于float 和 double 输入时 如果是float必须用%f double必须用%lf这样对么 但是输出时有问题

C语言中printf输出float和double都用%f么(scanf又如何)

C语言中float与double在程序中输出的分别是多少位?

关于C语言中double型输出的问题

C语言中的小数float,double

float,double类型小数计算结果为啥不一样