当前位置: 首页 > 知识库问答 >
问题:

为什么两个float类型变量有不同的值[duplicate]

狄奕
2023-03-14

我有两个接近1000大小的整数向量,我要做的是检查这两个向量的平方整数和是否相同。所以我编写以下代码:

std::vector<int> array1;
std::vector<int> array2;
... // initialize array1 and array2, and in the experiment all elements
    // in the two vectors are the same but the sequence of elements may be different.
    // For example: array1={1001, 2002, 3003, ....} 
   //               array2={2002, 3003, 1001, ....}
assert(array1.size() == array2.size());
float sum_array1 = 0;
float sum_array2 = 0;
for(int i=0; i<array1.size(); i++)
       sum_array1 +=array1[i]*array1[i];
for(int i=0; i<array2.size(); i++)
       sum_array2 +=array2[i]*array2[i];
 double sum_array1 = 0;
    double sum_array2 = 0;
    for(int i=0; i<array1.size(); i++)
           sum_array1 +=array1[i]*array1[i];
    for(int i=0; i<array2.size(); i++)
           sum_array2 +=array2[i]*array2[i];

共有1个答案

尹承泽
2023-03-14

浮点值具有有限的大小,因此只能以有限的精度表示实值。当您需要的精度超过它们所能存储的精度时,这会导致舍入误差。

特别是,当将一个较小的数字(如您正在求和的那些数字)加到一个大得多的数字(如您的累加器)上时,精度损失可能会比小数字大得多,从而产生重大误差;并且根据顺序的不同,错误也会有所不同。

通常,float具有24位精度,对应大约7位小数。您的累加器需要10位小数(约30位),因此您将经历这种精度损失。通常,double有53位(大约16位小数),因此可以精确地表示结果。

在这里,64位整数可能是最好的选择,因为所有的输入都是整数。使用整数可以避免精度损失,但如果输入太多或太大,则会带来溢出的危险。

如果不能使用足够宽的累加器,为了使误差最小化,可以对输入进行排序,使最小的值首先被累加;或者可以使用更复杂的方法,如Kahan求和。

 类似资料:
  • 问题内容: 考虑以下两种情况: (转到Playground链接) 第二个打印9.120000000000001,实际上很好 但是,为什么第一行打印9.12,但末尾没有…01?Go是否会将两个未类型化的常数相乘,并在编译时将它们简单地替换为9.12文字? 问题答案: 根据规格: 常量表达式总是精确地求值;中间值和常量本身可能需要比该语言中任何预声明类型支持的精度大得多的精度。 以来 是一个常数表达式

  • 输出如下:http://imgur.com/a/nu3n6

  • 我执行以下代码,没有错误,在输出中我看到了消息。你能解释一下这种奇怪的行为吗? 你可以查看在线演示

  • 我有一个类,只有两个字段:id、name 然后,在类中,我尝试使用两种不同的方法初始化User对象: 然后我就可以得到输出 有趣的是为什么u类是Main的内部类类型?但实际上我仍然可以使用和方法。

  • 但是,要添加到我的txt文件中的事务列表的类型是Transaction,而不是String。 作为一个例子,这里有一些用户存款情况下的代码。 理想情况下,我希望代码读取用户以前的事务,将他们的新事务添加到txt文件的末尾,然后在用户完成时将所有这些事务保存到同一个txt文件中。有没有一种方法可以读取用户以前的事务类型为Transaction而不是String,或者以某种方式将这两个列表组合起来,给

  • 问题内容: 这是我一直试图找到解决方案的问题。 我们有两个类定义。两个之一扩展另一个。 要求是应该有一个列表来保持对象扩展T 但是,当我尝试将TT对象(似乎不是T的子类)放入列表时,就会出现问题。 编译错误信息 类型List中的方法add(capture#2-of?extended Cell)不适用于参数(Cell) 问题答案: 您可以直接创建一个,这可以允许T的所有子类型进入列表。这实际上很难理