user-0 提问: 请教为什么printf("result is=%f\n",1234567.1);返回的是1234567.125 ？

回复:
user: user-1
content: 换成%.1f就是输出一位小数了。同理%.3f就是输出3位小数

user: user-2
content: .125就是八分之一。说明浮点指数截断后，最后一个阶是二的负三次幂。

user: user-3
content: ……人家跟你说得清清楚楚，你在这里质疑计算机有什么用？  不得不说在我看来你在钻牛角尖。明明自己去学习并实践一下浮点数的十进制如何转二进制就能明白的，建议再去研究一下计算机组成原理，真的明白原理后，我想你的计算机无用论会不攻自破。  另外，我想说计算机不是万能的，他能帮我们提高效率，但是你如果真的想得到特别特别准确，甚至说绝对准确的数据是不可能的。而且现实生活中也不是需要绝对准确的数据，对数据的要求都是在一个可接受的误差范围内，这也是学计算机要学习数值计算方法的原因。绝大多数情况下，我们需要的是满足误差范围的数据。

user: user-4
content: 这种应该算误差吧，要保留1位小数的话用％.1f

user: user-5
content: 有效位数超出了

user: user-6
content: 这个是编译器的问题

user: user-7
content: 简短截说 10进制小数就是用1/10,1/100,1/1000，……分 2进制小数就是用1/2,1/4,1/8,……分 N进制小数就是用1/N,1/(N*N),1/(N*N*N),……分 所以如果限制最小的用来分的阶数（也就是小数点后最多多少位），M进制小数和N进制小数对有些数两者都能精确表示，对有些数两者只有其一能精确表示，对有些数，两者都不能精确表示。 如果不限制最小的用来分的阶数（也就是小数点后最多多少位，也就是允许使用无限位，不一定非得是循环小数），那M进制小数和N进制小数都能精确表示任何有理数。

user: user-7
content: 引用 52 楼 oracleperl 的回复:引用 赵老师好 请教下 1. 如果是整数，二进制和十进制互转没有问题对吧？ 2.二进制转十进制也是可以精确转的对吧？，比如如下演算    二进制0.1111= 1*(1/2)+1*(1/4)+(1/8)+1/16= 7/8 3. 十进制小数转二进制就不一定能精确转了对吧？似乎是二进制没法记录10进制的所有值    或者说二进制的数值是十进制数值的子集？我这样理解对吧？   但我还没搞明白十进制转二进制的原理 1.对 2.不对 3.对。半对（二进制没法记录10进制的所有值，10进制也没法记录二进制的所有值，二进制的数值和十进制数值之间谁都不是谁的子集）。错。 N（正整数N≥2）进制的小数比如  N=2，2进制： 10.11 W1=1,W0=0,W-1=1,W-2=1其中-1,-2是下标， 对应数值为W1*N^1+W0*N^0+W-1*N^-1+W-2*N^-2其中^表示指数  N=3，3进制： 20.11 W1=2,W0=0,W-1=1,W-2=1其中-1,-2是下标， 对应数值为W1*N^1+W0*N^0+W-1*N^-1+W-2*N^-2其中^表示指数  N=10，10进制： 90.11 W1=9,W0=0,W-1=1,W-2=1其中-1,-2是下标， 对应数值为W1*N^1+W0*N^0+W-1*N^-1+W-2*N^-2其中^表示指数  显然： N=3,3进制 0.1 W0=0,W-1=1,对应数值为W0*N^0+W-1*N^-1即0*3^0+1*3^-1=0.33333333333333无限循环，无法用长度有限的10进制表示 同理，对有些长度有限的10进制小数，无法用长度有限的2进制表示

user: user-8
content: 引用 46 楼 oracleperl 的回复:[quote=引用 45 楼 青蛙工作室 的回复:]严重怀疑楼主是来钓鱼提升CSDN的活跃度的，这么一个基础的问题纠缠了5页，而且看楼主的ID，oracle、perl，3年码龄，根本就不像一个刚接触计算机的小白。各位热心的CSDNer，可以散了。 对你来说是基础的，对别人来说未必是基础的 [/quote]  那你倒是解释一下你的ID，oracle perl，这是一个不懂电脑的小白能想到的？而且在CSDN已有3年，3年啊，哪怕新生儿都上幼儿园了。

user: user-9
content: %f改为%.1f

user: user-10
content: 好厉害👍，真心都大神！

user: user-11
content: 厉害了，不知道是咋回事

user: user-12
content: 不管你怎么输入，都不会输出0.125那么大的精度偏差。 出现精度偏差的原因是因为计算机存储的是二进制，当你定义一个数值之后，计算机会自动转换成二进制对象，对于整数部分处理起来比较简单，二进制 可以表示出可表示范围内的所有整数，但是小数点以下部分就比较难了。比如0.5可以用2的负1次方。即.1；0.25比如0.5可以用2的负2次方，即.01；0.75比如0.5可以用2的负1次方+可以用2的负2次方，即.11。（这里只是表述一个小数，实际上小数点也会被转换成一个二进制，即一个double或者long型对象，会有相应位数表示正负和小数点的位置。），因此小数部分的表达公式是，进制数乘以该位置的负指数次之后。例如一个二进制.101=1*2^-1+0*2^-2+1*2^-3。 如果你数学足够好，你就会发现，二进制可以表示成唯一的一个十进制数，但是并不是所有十进制数都可以用二进制表示出来，但是可以不断地去用二进制进行逼近。因此在精度范围内，两者输出是一致的。但是如果超过了精度范围，你就会发现两者出现不一致。这个误差是由于设计程序语言设计之初就导致的误差，是系统误差。因此我们在进行一个高精度计算时（或者在进行金融相关的计算与数据存储时候），并不会使用int、long、double这些数据类型，而是使用BigDecimal。

user: user-13
content: 引用 32 楼 oracleperl 的回复:[quote=引用 22 楼 lin5161678 的回复:][quote=引用 13 楼 oracleperl 的回复:] i请教这句"作为常识，大多数十进制有限位小数不能精确转换为二进制。“ 该怎么理解？ 因为 十进制不是2的次幂 所以 有的十进制小数无法用二进制精确表示 如果是 八进制小数 十六进制小数 那么 取值范围之内 就都能精确的用二进制表示[/quote] 说不通啊，举个例子？ 我现在想打印给float赋值123.99 然后就错了？理由是十进制没法转成二进制？ 那么计算机还有什么用？我们还敢写程序吗？比如工资计算程序，就算错了？ [/quote] 工资本来也不是按浮点处理的，  引用 47 楼 oracleperl 的回复:[quote=引用 44 楼 zlzfc 的回复:]printf("result is=%.2f\n", 123456.99f); 就可以了 谢谢。这样我知道可以，但我不知道为什么那样是错的 我看了书《深入理解计算机系统》，说只有2的N次方的进制之间的转换才能确保一致 书上说 float32位，尾数24位，假设4个bits表示一个十进制数字，难道6个4位不能表示123.99吗？ [/quote] 你把123.99转为2进制表示就知道了

user: user-14
content: 引用 47 楼 oracleperl 的回复:[quote=引用 44 楼 zlzfc 的回复:]printf("result is=%.2f\n", 123456.99f); 就可以了 谢谢。这样我知道可以，但我不知道为什么那样是错的 我看了书《深入理解计算机系统》，说只有2的N次方的进制之间的转换才能确保一致 书上说 float32位，尾数24位，假设4个bits表示一个十进制数字，难道6个4位不能表示123.99吗？ [/quote]不停说话是没用的 这东西能实践  0.2611 十进制 转换为二进制小数 写出来  转换过程 转换结果都"写"出来 自己实际操作一次 就什么都明白了 来吧干活

user: user-0
content: 引用 44 楼 zlzfc 的回复:printf("result is=%.2f\n", 123456.99f); 就可以了 谢谢。这样我知道可以，但我不知道为什么那样是错的 我看了书《深入理解计算机系统》，说只有2的N次方的进制之间的转换才能确保一致 书上说 float32位，尾数24位，假设4个bits表示一个十进制数字，难道6个4位不能表示123.99吗？

user: user-0
content: 引用 45 楼 青蛙工作室 的回复:严重怀疑楼主是来钓鱼提升CSDN的活跃度的，这么一个基础的问题纠缠了5页，而且看楼主的ID，oracle、perl，3年码龄，根本就不像一个刚接触计算机的小白。各位热心的CSDNer，可以散了。 对你来说是基础的，对别人来说未必是基础的

user: user-8
content: 严重怀疑楼主是来钓鱼提升CSDN的活跃度的，这么一个基础的问题纠缠了5页，而且看楼主的ID，oracle、perl，3年码龄，根本就不像一个刚接触计算机的小白。各位热心的CSDNer，可以散了。

user: user-0
content: 引用 赵老师好 请教下 1. 如果是整数，二进制和十进制互转没有问题对吧？ 2.二进制转十进制也是可以精确转的对吧？，比如如下演算    二进制0.1111= 1*(1/2)+1*(1/4)+(1/8)+1/16= 7/8 3. 十进制小数转二进制就不一定能精确转了对吧？似乎是二进制没法记录10进制的所有值    或者说二进制的数值是十进制数值的子集？我这样理解对吧？   但我还没搞明白十进制转二进制的原理

user: user-15
content: 引用 25 楼 oracleperl 的回复:[quote=引用 21 楼 真相重于对错 的回复:][quote=引用 20 楼 oracleperl 的回复:][quote=引用 17 楼 真相重于对错 的回复:]从数学的角度讲，数是无限的，而计算机只能表示有限的数，就算整形也受到位数的限制，内存的容量不管多大，也有尽头。而数是无限的。因此计算机无法表示所有的数。这个并不是计算机无用。。 谢谢赵老师，这个我能理解 但是为什么printf("result is=%f\n",123.99f); 这么小的一个十进制数，printf不能返回正确的值？ 难道这个123.99转二进制也会转错？这是我不理解的。 [/quote] 你要了解为什么会转错，那么先要了解，计算机中如何存储整数，进而了解计算机中如何存储小数。了解这些就没有疑惑，不了解这些，别人也没法讲清楚。[/quote] 大神，别人没法讲清楚的事，包括书籍，C标准文档，都是“别人” 那么我如何了解清楚呢？[/quote]  这个梗不错，有开心麻花的范儿。