Check precision to nth decimal place?

2019-07-11 19:01发布

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;
}

5条回答
贪生不怕死
2楼-- · 2019-07-11 19:35

Store the measured FP value as a scaled integer:

ix = int(fp * 10000)

You can then do direct comparisons with the required precision.

查看更多
一夜七次
3楼-- · 2019-07-11 19:38

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
查看更多
Bombasti
4楼-- · 2019-07-11 19:43

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.

查看更多
等我变得足够好
6楼-- · 2019-07-11 19:58

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.

查看更多
登录 后发表回答