检查精确到小数点后第 n 位?

发布于 2024-12-06 00:04:39 字数 3476 浏览 1 评论 0原文

我必须计算热板的值,并使其精确到小数点后第一位。我很难弄清楚如何检查所有数组值(如果它们发生了变化)。我发现 724 次运行后,小数点后第四位(正在打印的数量)没有变化。

有没有办法只比较小数点后第 n 位的双精度变量?

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

const int ARRAY_SIZE = 20;
const int NEIGHBORS = 4;

void initialize(double hot_plate[][ARRAY_SIZE]);
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
               const string FILE_NAME);

double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
                const int CELL_X, const int CELL_Y);

int main()
{
    double hot_plate[ARRAY_SIZE][ARRAY_SIZE];

    initialize(hot_plate);

    string file_name = "hot_plate.csv";

    //accuracy up to 4 decmials
    int runs = 724;
    while ( runs > 0)
    {
        for (int i = 0; i < ARRAY_SIZE; i++)
        {
            for (int j = 0; j < ARRAY_SIZE; j++)
            {
                if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
                {
                    hot_plate[i][j] = sum_cell(hot_plate, j, i);
                }
            }
        }
        runs--;
    }

    if (writeFile(hot_plate, file_name))
    {
        cout << "File wrote correctly\n";
    }
    else
    {
        cout << "The file did not write!\n";
    }

    //system("pause");

    return 0;
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Completed Code ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
                const int CELL_X, const int CELL_Y)
{
    /* This code should never go out of bounds as it's in an if statement
       if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
    */
    double cell_num = HOT_PLATE[CELL_X - 1][CELL_Y]; // Top
    cell_num += HOT_PLATE[CELL_X][CELL_Y - 1]; // Left
    cell_num += HOT_PLATE[CELL_X][CELL_Y + 1]; // Right
    cell_num += HOT_PLATE[CELL_X + 1][CELL_Y]; // Bottom

    cell_num /= NEIGHBORS;

    return cell_num;
}

// setup the Array so all values are defined when starting
void initialize(double hot_plate[][ARRAY_SIZE])
{
    for (int i = 0; i < ARRAY_SIZE; i++)
    {
        for (int j = 0; j < ARRAY_SIZE; j++)
        {
            if (i == 0 || i == ARRAY_SIZE - 1)
            {
                if (j == 0 || j == ARRAY_SIZE - 1)
                {
                    hot_plate[i][j] = 0.0;
                }
                else
                {
                    hot_plate[i][j] = 100.0;
                }
            }
            else
            {
                hot_plate[i][j] = 0.0;
            }
        }
    }
}

// Write the data to the CSV file
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
               const string FILE_NAME)
{
   // open the file
   ofstream fout(FILE_NAME);
   if (fout.fail())
      return false;

   for (int i = 0; i < ARRAY_SIZE; i++)
   {
       for (int j = 0; j < ARRAY_SIZE; j++)
       {
           fout << HOT_PLATE[i][j];
           if ( j < ARRAY_SIZE - 1)
           {
               fout << ", ";
           }
           else if (i != ARRAY_SIZE - 1)
           {
               fout << endl;
           }
       }
   }

   // close the input stream from the file.
   fout.close();
   return true;
}

I have to calculate the values of a hot plate and have it accurate only to the first decimal place. I am stumped on trying to figure out how to check all the array values if they changed. I found out that 724 runs made no change after that to the 4th decimal (how many were being printed).

Is there a way to compare doubles variables only up to the n-th decimal place?

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

const int ARRAY_SIZE = 20;
const int NEIGHBORS = 4;

void initialize(double hot_plate[][ARRAY_SIZE]);
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
               const string FILE_NAME);

double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
                const int CELL_X, const int CELL_Y);

int main()
{
    double hot_plate[ARRAY_SIZE][ARRAY_SIZE];

    initialize(hot_plate);

    string file_name = "hot_plate.csv";

    //accuracy up to 4 decmials
    int runs = 724;
    while ( runs > 0)
    {
        for (int i = 0; i < ARRAY_SIZE; i++)
        {
            for (int j = 0; j < ARRAY_SIZE; j++)
            {
                if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
                {
                    hot_plate[i][j] = sum_cell(hot_plate, j, i);
                }
            }
        }
        runs--;
    }

    if (writeFile(hot_plate, file_name))
    {
        cout << "File wrote correctly\n";
    }
    else
    {
        cout << "The file did not write!\n";
    }

    //system("pause");

    return 0;
}

////////////////////////////////////////////////////////////////////////////////
//////////////////////////// Completed Code ////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

double sum_cell(const double HOT_PLATE[][ARRAY_SIZE],
                const int CELL_X, const int CELL_Y)
{
    /* This code should never go out of bounds as it's in an if statement
       if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)
    */
    double cell_num = HOT_PLATE[CELL_X - 1][CELL_Y]; // Top
    cell_num += HOT_PLATE[CELL_X][CELL_Y - 1]; // Left
    cell_num += HOT_PLATE[CELL_X][CELL_Y + 1]; // Right
    cell_num += HOT_PLATE[CELL_X + 1][CELL_Y]; // Bottom

    cell_num /= NEIGHBORS;

    return cell_num;
}

// setup the Array so all values are defined when starting
void initialize(double hot_plate[][ARRAY_SIZE])
{
    for (int i = 0; i < ARRAY_SIZE; i++)
    {
        for (int j = 0; j < ARRAY_SIZE; j++)
        {
            if (i == 0 || i == ARRAY_SIZE - 1)
            {
                if (j == 0 || j == ARRAY_SIZE - 1)
                {
                    hot_plate[i][j] = 0.0;
                }
                else
                {
                    hot_plate[i][j] = 100.0;
                }
            }
            else
            {
                hot_plate[i][j] = 0.0;
            }
        }
    }
}

// Write the data to the CSV file
bool writeFile(const double HOT_PLATE[][ARRAY_SIZE],
               const string FILE_NAME)
{
   // open the file
   ofstream fout(FILE_NAME);
   if (fout.fail())
      return false;

   for (int i = 0; i < ARRAY_SIZE; i++)
   {
       for (int j = 0; j < ARRAY_SIZE; j++)
       {
           fout << HOT_PLATE[i][j];
           if ( j < ARRAY_SIZE - 1)
           {
               fout << ", ";
           }
           else if (i != ARRAY_SIZE - 1)
           {
               fout << endl;
           }
       }
   }

   // close the input stream from the file.
   fout.close();
   return true;
}

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

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

发布评论

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

评论(5

洒一地阳光 2024-12-13 00:04:39

有没有办法只比较小数点后第 n 位的双精度变量?

是的,检查它们之间的差的绝对值是否小于10^-n。

Is there a way to compare doubles variables only up to the n-th decimal place?

Yes there is, check whether the absolute value of the difference between them is less than 10^-n.

月下凄凉 2024-12-13 00:04:39

使用此函数,

double getUpToDecPlace (double value, int decPlace)
{
    int dec = 1;
    for (int i = 0; i < decPlace; i++)
    {
        dec *= 10;
    }
    return floor(value*dec + 0.5)/dec;
}

getUpToDecPlace(12.345678, 2) 将返回 12.35,您可以将 double 与任意小数位进行比较:

double var1 = 12.345678;
double var2 = 12.351234;
bool comp1 = (getUpToDecPlace(var1, 2) == getUpToDecPlace(var2, 2)); // true
bool comp2 = (getUpToDecPlace(var1, 3) == getUpToDecPlace(var2, 3)); // false

With this function

double getUpToDecPlace (double value, int decPlace)
{
    int dec = 1;
    for (int i = 0; i < decPlace; i++)
    {
        dec *= 10;
    }
    return floor(value*dec + 0.5)/dec;
}

which would return 12.35 for getUpToDecPlace(12.345678, 2), you can compare doubles up to an arbitrary decimal place:

double var1 = 12.345678;
double var2 = 12.351234;
bool comp1 = (getUpToDecPlace(var1, 2) == getUpToDecPlace(var2, 2)); // true
bool comp2 = (getUpToDecPlace(var1, 3) == getUpToDecPlace(var2, 3)); // false
看透却不说透 2024-12-13 00:04:39

这里有很多问题。

  1. 您正在就地更新 hot_plate 数组。因此,您在“上一代”中使用的一些值已经在当前一代中更新了!您必须在单独的数组中计算每一代,然后将其复制回“主”hot_plate 数组。

  2. 如果您希望最终结果精确到小数点后一位,则在值变化不超过 0.1 之前继续下去是不够的。例如,某些值可能会在十代之后变化超过 0.05,这相当于变化超过 0.5。事实上,这是一个非常棘手的问题:它需要对初始条件如何随时间演变进行全局分析。

  3. 您确定sum_cell正确吗?下一代hot_plate[i][j]的温度肯定取决于hot_plate[i][j]的当前值,而不仅仅是取决于它的邻居?

另外,这看起来有点傻:

for (int i = 0; i < ARRAY_SIZE; i++)
{
    for (int j = 0; j < ARRAY_SIZE; j++)
    {
        if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)

我建议等效的公式:

for (int i = 1; i < ARRAY_SIZE - 1; i++)
{
    for (int j = 1; j < ARRAY_SIZE - 1; j++)

至于测试小数点后第 n 位的相等性,其他海报已经涵盖了这一点。

There are so many problems here.

  1. You are updating the hot_plate array in-place. So some of the values you use from the 'previous generation' have already been updated in the current generation! You have to compute each generation in a separate array, and then copy it back to the 'master' hot_plate array.

  2. If you want the final result accurate in the first decimal place, it's not enough to continue until the values don't change by more than 0.1. For instance, some values might change by more than 0.05 for ten more generations, which would amount to a change of more than 0.5. In fact, this is a very tricky issue: it requires a global analysis of how the initial conditions evolve over time.

  3. Are you sure you have sum_cell right? The temperature of hot_plate[i][j] at the next generation should surely depend on the current value of hot_plate[i][j], and not just on its neighbours?

Also, this looks a bit silly:

for (int i = 0; i < ARRAY_SIZE; i++)
{
    for (int j = 0; j < ARRAY_SIZE; j++)
    {
        if (i > 0 && i < ARRAY_SIZE - 1 && j > 0 && j < ARRAY_SIZE - 1)

I suggest the equivalent formulation:

for (int i = 1; i < ARRAY_SIZE - 1; i++)
{
    for (int j = 1; j < ARRAY_SIZE - 1; j++)

As for testing equality to the nth decimal place, other posters have covered that.

喜你已久 2024-12-13 00:04:39

将测得的 FP 值存储为缩放整数:

ix = int(fp * 10000)

然后您可以与所需的精度进行直接比较。

Store the measured FP value as a scaled integer:

ix = int(fp * 10000)

You can then do direct comparisons with the required precision.

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