如何解决 C++ 中浮点运算的舍入问题?

发布于 2024-10-05 07:26:54 字数 749 浏览 8 评论 0原文

我遇到了一些浮点运算不准确的问题。我正在尝试根据加权公式计算分数,其中每个输入变量的权重约为下一个重要变量的 20 倍。然而,输入是实数,所以我最终使用双精度来存储结果。下面的代码存在丢失E1和E2之间差异的问题。

这段代码对性能敏感,所以我需要找到这个问题的有效答案。我想将我的输入乘以一百,然后使用 int (因为我认为这足够精确),但我怀疑这是最好的解决方案,因此出现了问题。

#include <iostream>

int main()
{
    double score1, score2;
    float a  = 2.75 ;
    float b  = 5.25 ;
    float c  = 5.25 ;
    float d  = 2.75 ;
    float E1 = 3    ;
    float E2 = 6    ;

    score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;
    score2 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E2 ;

    std::cout << score1 << std::endl;
    std::cout << score2 << std::endl;

    std::cin.get();
    return 0;
}

//ouputs:
//102.388
//102.388

Im running into some issues with floating point arithmetic not being accurate. I'm trying to calculate a score based on a weighted formula where every input variable weighs about as much as 20 times the next significant one. The inputs however are real numbers, so I ended up using a double to store the result. The code below has the problem of losing the difference between E1 and E2.

This code is performance sensitive, so I need to find an efficient answer to this problem. I thought of multiplying my inputs by a hundred and then using an int (since that would be precise enough I think), but I doubt that is the best solution, hence the question.

#include <iostream>

int main()
{
    double score1, score2;
    float a  = 2.75 ;
    float b  = 5.25 ;
    float c  = 5.25 ;
    float d  = 2.75 ;
    float E1 = 3    ;
    float E2 = 6    ;

    score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;
    score2 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E2 ;

    std::cout << score1 << std::endl;
    std::cout << score2 << std::endl;

    std::cin.get();
    return 0;
}

//ouputs:
//102.388
//102.388

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

天涯沦落人 2024-10-12 07:26:54
  1. 您没有输出整个值,请使用 cout <<设置精度(位数)<<分数1 << endl;
  2. 在分数计算中您需要多少个有效数字?
  1. you are not outputting the entire value, use cout << setprecision(number_of_digits) << score1 << endl;
  2. how many valid digits do you need in your score computation?
記憶穿過時間隧道 2024-10-12 07:26:54

我想将输入乘以一百,然后使用 int (因为我认为这足够精确),但我怀疑这是最好的解决方案

鉴于您显示的值,我会说它是。

I thought of multiplying my inputs by a hundred and then using an int (since that would be precise enough I think), but I doubt that is the best solution

Given the values you've shown, I would say it is.

枕头说它不想醒 2024-10-12 07:26:54

http://ideone.com/qqTB3 告诉你差异并没有丢失,而是实际上和你一样大' dexpect(最高浮点精度,对于 double 来说是 15 位小数)。

http://ideone.com/qqTB3 shows you that the difference is not lost, but actually as big as you'd expect (up to floating point accuracy, which is 15 decimal digits for double).

如果没有你 2024-10-12 07:26:54

让我们看看这段代码中发生了什么:

score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;

// Multiplication division happens first:

float  tmp1 = static_cast<float>(20) * b;      // 20 cast to float.
float  tmp2 = static_cast<float>(1)  * a;      // 1  cast to float.
double tmp3 = 0.05   * static_cast<double>(d); // d converted to double as 0.05 is double
double tmp4 = 0.0001 * static_cast<double>(E1);// E1 cast to double as 0.0001 is double

// Addition and subtraction now happen
float  tmp5  = tmp1 - tmp2;
double tmp6  = static_cast<double>(tmp5) + tmp3; // tmp5 cast to double as tmp3 is a double.
double tmp7  = tmp6 + tmp4;
score1       = tmp7;

如果我们在脑海中执行此操作:

tmp1 = 105.0
tmp2 =   2.75
tmp3 =   0.1375
tmp4 =   0.0003
tmp5 = 107.75
tmp6 = 107.8875
tmp7 = 107.8878

这些值的精度应该保持不变:
但是当你打印出来时,双精度数的默认精度是小数点后 3 位。

std::cout << 107.8878;
> 107.888

因此设置精度:

std::cout << std::setprecision(15) << 107.8878 << "\n";
> 107.8878

Lets see what is happening in this code:

score1 = 20 * b - 1 * a + 0.05 * d  /* - 0.0025 * c*/ + 0.0001 * E1 ;

// Multiplication division happens first:

float  tmp1 = static_cast<float>(20) * b;      // 20 cast to float.
float  tmp2 = static_cast<float>(1)  * a;      // 1  cast to float.
double tmp3 = 0.05   * static_cast<double>(d); // d converted to double as 0.05 is double
double tmp4 = 0.0001 * static_cast<double>(E1);// E1 cast to double as 0.0001 is double

// Addition and subtraction now happen
float  tmp5  = tmp1 - tmp2;
double tmp6  = static_cast<double>(tmp5) + tmp3; // tmp5 cast to double as tmp3 is a double.
double tmp7  = tmp6 + tmp4;
score1       = tmp7;

If we do this in our heads:

tmp1 = 105.0
tmp2 =   2.75
tmp3 =   0.1375
tmp4 =   0.0003
tmp5 = 107.75
tmp6 = 107.8875
tmp7 = 107.8878

The precision should hold for those values:
But when you print out the default precision for doubles is 3 decimal places.

std::cout << 107.8878;
> 107.888

So set the precision:

std::cout << std::setprecision(15) << 107.8878 << "\n";
> 107.8878
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文