Open alwaystest opened 7 years ago
标签(空格分隔): 基础
计算机界流传着这么一个区别AI与人类的方法:
问: 0.2 + 0.1 = ?
0.2 + 0.1 = ?
如果是AI,答案就不是刚刚好0.3。
当然,不是说用电脑的计算器程序算这个结果,而是在编程的时候直接输出0.1 + 0.2。
0.1 + 0.2
大学学基础课的时候曾经提到过这一点,当时也没有仔细研究,就当是基础概念记住了,小数在计算机中存储会有误差,有些小数不能准确表达。
目前的计算机是使用二进制来存储和表达数据的,十进制的数据在计算机中会被转换为二进制的数据。
整数部分,十进制能表示的最小有效单位是1,二进制也是,我们可以用几个1来表达整数部分,
比如十进制的123,用十进制表达,就是 1 * 10^2 + 2 * 10^1 + 3 * 10^0
1 * 10^2 + 2 * 10^1 + 3 * 10^0
用二进制表示:1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0即1111011
1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0
1111011
所以整数表达不存在二进制没办法准确表示十进制的数值。
但是小数部分就不一样了。
同样是3位小数,十进制可以表示的最小单位是 0.001, 二进制可以表示的最小单位是 0.001 转换成十进制就是2^-3 == 0.125。
0.001
2^-3 == 0.125
这样,能表达的数就成了这样,十进制可以表示1000个值,二进制只能精确表示8个值,这8个值都是可以表达的最小单位的整数倍。比如0.5就是4 * 0.125,所以0.5这个值是可以用3位精度的二进制小数精确表达的,而0.1,0.2,0.3等等不是0.125整数倍的小数就无法使用三位精度的二进制小数来精确表达的。
1000
8
0.5
4 * 0.125
0.1
0.2
0.3
0.125
扩展到float,哪怕它使用了比3位更大的小数精度来表示一个数字,但是很遗憾即使是这么小的单位,也不能整除0.2,0.3这些数值,所以也就无法精确表示这些值,所以在代码中计算0.1 + 0.2的结果就没办法精确的表示位0.3,只能取一个最近似的数来表示。
Folat 不能精确表示小数
标签(空格分隔): 基础
计算机界流传着这么一个区别AI与人类的方法:
问:
0.2 + 0.1 = ?
如果是AI,答案就不是刚刚好0.3。
当然,不是说用电脑的计算器程序算这个结果,而是在编程的时候直接输出
0.1 + 0.2
。大学学基础课的时候曾经提到过这一点,当时也没有仔细研究,就当是基础概念记住了,小数在计算机中存储会有误差,有些小数不能准确表达。
目前的计算机是使用二进制来存储和表达数据的,十进制的数据在计算机中会被转换为二进制的数据。
整数部分,十进制能表示的最小有效单位是1,二进制也是,我们可以用几个1来表达整数部分,
比如十进制的123,用十进制表达,就是
1 * 10^2 + 2 * 10^1 + 3 * 10^0
用二进制表示:
1 * 2^6 + 1 * 2^5 + 1 * 2^4 + 1 * 2^3 + 0 * 2^2 + 1 * 2^1 + 1 * 2^0
即1111011
所以整数表达不存在二进制没办法准确表示十进制的数值。
但是小数部分就不一样了。
同样是3位小数,十进制可以表示的最小单位是
0.001
, 二进制可以表示的最小单位是0.001
转换成十进制就是2^-3 == 0.125
。这样,能表达的数就成了这样,十进制可以表示
1000
个值,二进制只能精确表示8
个值,这8个值都是可以表达的最小单位的整数倍。比如0.5
就是4 * 0.125
,所以0.5
这个值是可以用3位精度的二进制小数精确表达的,而0.1
,0.2
,0.3
等等不是0.125
整数倍的小数就无法使用三位精度的二进制小数来精确表达的。扩展到float,哪怕它使用了比3位更大的小数精度来表示一个数字,但是很遗憾即使是这么小的单位,也不能整除
0.2
,0.3
这些数值,所以也就无法精确表示这些值,所以在代码中计算0.1 + 0.2
的结果就没办法精确的表示位0.3
,只能取一个最近似的数来表示。