A) 已详尽讨论的主题 - double 和 float 之间的精度。 B)需要一些生活和学习方面的建议

问题描述 投票:0回答:1

A部分) 大家好,我是CS一年级学生。在早期的测验中,有一些花车是双打的。我在提交后发布此内容。所以我认为我没问题,实际上我希望没人关心。

float price1 = 17.96f, price3 = 17.98f;
double price2 = 17.96, price4 = 17.98;
printf("1. 17.96 = %f (as cents:%d)\n", price1, (int)(price1 * 100));
printf("2. 17.96 = %lf (as cents:%d)\n", price2, (int)(price2 * 100));
printf("3. 17.98 = %f (as cents:%d)\n", price3, (int)(price3 * 100));
printf("4. 17.98 = %lf (as cents:%d)\n", price4, (int)(price4 * 100));

输出是

1. 17.96 = 17.959999 (as cents:1795)
2. 17.96 = 17.960000 (as cents:1796)
3. 17.98 = 17.980000 (as cents:1798)
4. 17.98 = 17.980000 (as cents:1798)

问题是为什么 (int)(price1 * 100) 结果是 1795 或 1796。 我将打印格式更改为小数点后 25 位,看看内存中存储的“实数”是多少。 输出结果

1. 17.96 = 17.9599990844726562500000000 (as cents:1795)
2. 17.96 = 17.9600000000000008526512829 (as cents:1796)
3. 17.98 = 17.9799995422363281250000000 (as cents:1798)
4. 17.98 = 17.9800000000000004263256415 (as cents:1798)

我很容易发现Price1小数部分的第7个数字是0,这使得之前的数字是17.959999。这个数字 * 100 然后转换为 INT 确实是 1795。但很快我注意到 Price3(也是一个浮点数)乘以 100 转换为 Int 是 1798 而不是我想象的 1797!在花了很多时间与 ChatGPT 4.0 交谈后(为什么不首先使用 Stackoverflow?caz chatGPT Plus 售价 31.5 加元!我必须让它物有所值!),它告诉我“啊你是对的,你的教授错了 ~” enter image description here

但我不是一个因为AI做不到就放弃的人。花了将近半天的时间,我得到了一个结论(我不知道对还是错)。参与计算的数字不是“实际存储的数字”,而是使用默认说明符打印的数字,最多可达 6 位十进制数字。所以在计算“Price3 * 100”时,price3不是“17.9799995422363281250000000”而是17.980000。因此,(int) (price3 * 100) 的结果是 1798。

我想确认我的猜测。或者如果可能的话提供一个链接。 (抱歉!今天真的花了很多时间,没有精力去goole了)

B 部分)

我知道这个问题是非常基本的,甚至是愚蠢的。但我还是花了半天多的时间才找到答案(主要是和AI对话),甚至没有得到答案。我知道在这条路上我以后还会面临更多的问题。我知道“首先如何,其次为什么”在这个领域非常重要,基本上我猜的一切。只是因为喜欢把所有事情都弄清楚,并花时间在上面。我知道我无法弄清楚所有事情,未来要学习的东西越来越多。那么有人对这条道路上的新学生有建议吗?

c floating-point double precision floating-accuracy
1个回答
0
投票

float
double
是一些整数乘以 2 的幂。

17.96
17.98
不能 完全这样表示。

而是使用附近的可表示数字,该数字位于所需代码浮点常量的上方或下方。

按 100 缩放会产生 额外舍入效应 - 可能会向上一点或向下一点。产品可能是 1796、1798 或略高于或略低于。


C23 可选择提供十进制浮点,最适合解决类似的十进制问题。


在没有清楚了解边缘效应的情况下,不要对浮点计算结果使用像

(int)
这样的粗略转换。

应用

int
转换是有问题的编码,因为轻微的乘积计算会导致 1795 或 1797,因为之前的乘积是 1795.999...1797.999...使用
lround()
会更有意义。


要使用

float
(一个糟糕的主意)扩大货币规模,请乘以 100.0(
double
)并使用
llround()
lround()

要使用

double
将货币缩放为整数,请乘以 100.0L(a
long double
)并使用
llroundl()
lroundl()

额外的精度将有助于解决边缘情况。

© www.soinside.com 2019 - 2024. All rights reserved.