!!!!!!C菜鸟问题 恳请高手帮忙!!!!!!!

问题很菜,肯请高手不要笑话
#include<stdio.h>
#include<math.h>
void main()
{
double a,b,t;
scanf("%d%d",&a,&b);
t=a>b?a:b;
printf("the bigger one is: %lf\n",t);
}
其实就是简单的两数比较大小然后输出大数,我试过了,在vc++6.0中运行时如果输入的两个数都是负数或两个数都不是负数,则都会输出较小的数,而如果只有一个数为负数时,则能正确地输出较大的数(也就是正数或零),这是为什么?
请各位高手先解决以上的问题再继续往下看
——————————————————————————————————————————————-——————————
其实这是以前百度上的一个问题,只不过解决得不怎么好,“解决的”那个人说把printf中的%d改成%lf(插一个小问题:谭浩强的书P81的第二个表格中没有说printf中存在%lf,但是P81的scanf则明确表示可以,那么在printf中能不能用%lf?),结果是不管输进什么都得到类似“the bigger one is: -92559592117432005000000000000000000000000000000000000000000000.000000
Press any key to continue”的结果。为什么啊??????
我想此问题无非就和三个地方挂钩(以下用①②③已注明)
#include<stdio.h>
#include<math.h>
void main()
{
① a,b,t;
scanf("%②%②",&a,&b);
t=a>b?a:b;
printf("the bigger one is: %③\n",t);
}
假如①可用char,short,int,long,float,double挨个替换
②可用c,d,f,lf挨个替换
③可用c,d,f,lf挨个替换
那么这样有很多种组合情况(当然有些组合纯粹是扯淡),我的主要问题是这些组合有那些是可行的?哪位高手能抽出一点宝贵的时间帮我详细详细详细讲讲这里面的知识点。这一类的问题已经困扰我好长时间了,谁能让我豁然开朗啊!提前谢谢所有回答此问题的人了.
在下自称菜鸟也是在高手面前表示谦虚而已,并不表示我真的刚刚开始学习C语言啊!做人要低调哦!所以请各位尽管讲,放开地讲!!!

你研究的东西,我不是学计算机的,所以我也很菜的,不知道研究这些东西有什么用.而且你最后说要用各种类型去替换,总结可行的规律,总结来干嘛呢?按照格式规规矩矩的使用函数就好了,你应该把精力转移到其他方面,人家都说double要用%lf,你硬要用%d给他赋值,便会出错嘛.
这些东西,一句话就可以点破的,楼上的已经说的很清楚了,我再说一下我的看法,我的电脑是32位的.

假如是读入,scanf(),里面的参数,就表明按怎样的格式读入数据,%d,表示读入的是有符号整形,且读4字节,若强制赋值给double,则double的低位4字节的内容就是这个整形的二进制码,高位4字节不变.

假如是输出,printf(),里面的参数,就表明按怎样的格式输出数据,%d,表示输出的是有符号整形,有符号整形各个二进位上的意义是有定义的,说就按有符号整形的格式输出.
同样输出整形,%u,%d,输出的东西不一样,因为他们二进位上的数意义.

解释一下你一开始的疑惑(我不知道你知不知道以下的东西,我假设你不知道,如果你知道,你应该不会有疑惑):

scanf("%d%d",&a,&b);假设分别读入5 6,
按我上面说的,
有符号的5=00000000000000000000000000000101
有符号的6=00000000000000000000000000000110

强制赋值给double类型,则赋值到低位4字节,高位4字节不变,以下是double a,b的二进制内容:
(未赋值之前a和b的都是=1100110011001100110011001100110011001100110011001100110011001100)
赋值后
a=1100110011001100110011001100110000000000000000000000000000000101
b=1100110011001100110011001100110000000000000000000000000000000110
注意到了吗?低位4字节完全和上面的一样.

t=a>b?a:b;
比较时,由于是double时,要按double的格式来比较,和整形不一样,上面a,b的那串字符,按double的格式来化成十进制数就是如下(没有错,且是负数,因为首位是符号位,1表示负数):
a=-92559592117432051000000000000000000000000000000000000000000000.000000
b=-92559592117432062000000000000000000000000000000000000000000000.000000

从数学来说,你说谁大?当然是a大啦.

printf("the bigger one is: %lf\n",t);
若按%lf输出,当然那上面a的64位按double的格式来化成十进制数,输出,当然就是
-92559592117432051000000000000000000000000000000000000000000000.000000

printf("the bigger one is: %d\n",t);
若按%d输出,我开始说了,%d,有符号的整形是4字节,那就输出低位的4字节.
a的低位4字节是0000000000000000000000000000000101,那当然是5了.

其他情况类似,没有必要去总结两个负数又输出什么的,按照格式规规矩矩的使用函数就好了.

假如我说得不好,你自己去研究解决,你应该去看看,unsigned int ,int ,double ,float 用二进制存储的格式,你就会豁然开朗了.
我可以简单讲一下,
int,
有符号,最高位为符号位,用补码存储.
无符号,用原码储存,无符号位.
float和double (科学计数法)类似,最高位是符号位,然后是指数位,最后是小数位.

以上数据我自己写函数算的,
另外,我想请问C或C++有没有提供什么函数可以直接输出某些变量的各个二进位的.
温馨提示:答案为网友推荐,仅供参考
第1个回答  2008-10-13
首先double在你的VC下占8字节,
当你用scanf("%d%d",&a,&b);输入时, %d表示仅用每个变量的低4个字节。
输入完毕后,比较代码比较的浮点数,而不是整数。浮点数是有特定的格式的,而你的a和b类似于(假定输入为5)cc cc cc cc 00 00 00 05,这样转换成的浮点数比较后就是你用printf("%lf")输出的结果。
这是因为你用的是Debug模式,VC帮你把堆栈都填了CC,所以会有这样的结果。
你用Release会有所不同。
第2个回答  2008-10-12
#include<stdio.h>
#include<math.h>
void main()
{
int a,b,t;
scanf("%d%d",&a,&b);
t=a>b?a:b;
printf("the bigger one is: %lf\n",t);
}

把程序中的double改成int即可正确运行,如上所示。
或者:
#include<stdio.h>
#include<math.h>
using namespace std;
void main()
{
double a,b,t;
scanf("%lf%lf",&a,&b);
t=a>b?a:b;
printf("the bigger one is: %lf\n",t);
}

%d是用来输入输出整数的,而%lf才是用来处理浮点数的,包括double,float,数据类型要一一致,否则会出现意想不到的结果。

当然,我以上说的都是废话,楼主当然知道这样是可以的。

对于,上面的现象,牵扯到数据类型在内存中的存储结构。既然楼主自称菜鸟,菜鸟现在不必知道那么多,只要按规矩办事就行。或许有一天你会明白的。

不过,我还想简单的说说,抽象的说一下,我也只能抽象的说一下。%d接收一个整数,用它来初始化一个double变量,致使double变量只是部分初始化。而一个未被初始化的double变量一般都是一个很大的负数,注意,这里所说的大是指它的绝对值大,而部分初始化后,它仍然是个负数,这会造成相同符号下,你输入的数值越大,而实际越小,就像4大于3,则-4小于-3性质是一样的,至于为什么一正一负,是正的大,这要牵扯到无符号数和有符号数的问题,把一个正数和负数都当做无符号数看待,正数都是小于负数的,所以,输入一个正数和一个负数,就像输入一个正数和一个较大的正数一样,结果是较大的正数是小的,负数也是小的,这就是所谓的歪打正着。
就说那么多吧。

忘了告诉你了,其实我也是莱鸟。以上是我睡觉时梦到的,信不信由你。。。
第3个回答  2008-10-12
符号扩展,内存模式,补码反码之类问题。
建议把精力集中在算法,编程思路上。
第4个回答  2008-10-12
首先,我的C++运行%lf没有问题
其次,出不同的结果,是在于读入与输出的机制上的(隐式转换等等)。
第5个回答  2008-10-12
你也够能钻的,我刚刚试了,想解决的确要花很多精力,但有个地方我想,的是“92559592117432005000000000000000000000000000000000000000000000.000000 ”这个数值跟电脑本身的内存型号有关,每个电脑的精确度都不一样,上面出现这么大的数是因为内存中64位的16位由输入的数字决定,剩余的48位就有内存本身的性质决定了,可能是1可能是0,一旦确定了,这就是该内存的特性了,以后都会以相同的方式补充0或1,其他情况也一样,都会因为位数的不足或溢出,来决定分配给变量的内存段中所有的位是0还是1