Home > Blockchain >  Creating two outputs for two, two dimentional arrays, using two nested for loops?
Creating two outputs for two, two dimentional arrays, using two nested for loops?

Time:10-10

Completely new to programming, i come from only excel experience so any help appreciated. The expressions calculate the altitude and bearing of the sun given your latitude, the hour of the day t and day of the year day.

The altitude calculation works fine, however the bearing calculation has sporadic nonsence negative values in the output.

These values which are stored in their respective arrays will be later used for other claculations.

Here's my block of code:

#include <iostream>
#include <cmath>
using namespace std;   

float degrees(float radians) { // gets degrees
return (radians * (180 / 3.14));
}

float radians(float degrees) { //gets radians
return (degrees * (3.14 / 180));
}

int main()
{

float latitude = 54;
// cout << "Enter latitude (in degrees): ";
// cin >> latitude;

float const sin_thi = sin(radians(latitude));
float const cos_thi = cos(radians(latitude));

// cout << "sin_thi: " << sin_thi << endl;
// cout << "cos_thi: " << cos_thi << endl;

float cos_omega[24];

// required for later calculation

for (int t = 0; t <= 23; t  )
{
    cos_omega[t] = cos(radians((15 * (t - 12))));
    // cout << cos_omega[t] << endl;
}

// gathering sun altitude and bearing data, storing into heap multidimentional arrays "alt_sun[][]" and "bearing_sun[][]".

auto alt_sun = new int [365][24];
auto bearing_sun = new int [365][24];

for (int day = 0; day <= 364; day  )
{
    for (int t = 0; t <= 23; t  )
    {
        alt_sun[day][t] = degrees(asin(((0.4 * cos(radians(0.99 * (day - 173)))) * sin_thi)   ((sin(((0.4 * cos(radians(0.99 * (day - 173)))) - 1.57)))) * (cos_omega[t] * cos_thi)));

        if (cos_omega[t] > 0)
            bearing_sun[day][t] = 360 - degrees(acos((((0.4 * cos(radians(0.99 * (day - 173)))) * cos_thi) - ((sin(((0.4 * cos(radians(0.99 * (day - 173)))) - 1.57))) * (cos_omega[t] * sin_thi))) / (cos(radians(alt_sun[day][t])))));

        else
            bearing_sun[day][t] = degrees(acos((((0.4 * cos(radians(0.99 * (day - 173)))) * cos_thi) - ((sin(((0.4 * cos(radians(0.99 * (day - 173)))) - 1.57))) * (cos_omega[t] * sin_thi))) / (cos(radians(alt_sun[day][t])))));         
    }
}

for (int day = 0; day <= 364; day  ) // to test calculation
{
    cout << "Day " << day << ":   " << bearing_sun[day][12] << endl;
}
}

Is there something fundamentally wrong with what im doing?

Expected results for the printed bearing values are to range from about 350 - 360 (roughly due to rounding on my previously made excel calculation). For example the first value should be about 355.

The code should run without user input and the problem should be explicit now.

My first thought was that the bad results were only happening when the else statement was used in the loop. But my limited amateur testing, like just running the single expression outside of the for loop and if statement, produced the same results. Which in my mind leaves only the expression itself, or the array as a possible cause.

An example screenshot of some of the output to the console, all the positive values are correct, all the negative values are wrong

Thanks

CodePudding user response:

When I run your program with UndefinedBehaviorSanitizer active, I get a run-time error message in line 48 and 51 that you are converting a NaN to an integer, which invokes undefined behavior. This means that your calculatings are producing a NaN.

When I run your program line by line in a debugger, I notice that when line 51, which is

bearing_sun[day][t] = degrees(acos((((0.4 * cos(radians(0.99 * (day - 173)))) * cos_thi) - ((sin(((0.4 * cos(radians(0.99 * (day - 173)))) - 1.57))) * (cos_omega[t] * sin_thi))) / (cos(radians(alt_sun[day][t])))));

is executed for the first time, it writes the value

-2147483648

into bearing_sun[0][0], which does not seem to be the intended value.

Since this line is a very long line, I modified it to several lines, so that I can examine the intermediate results more easily:

else
{
    auto intermediate_result_1 = (0.4 * cos(radians(0.99 * (day - 173)))) * cos_thi;
    auto intermediate_result_2 = sin(((0.4 * cos(radians(0.99 * (day - 173)))) - 1.57));
    auto intermediate_result_3 = cos_omega[t] * sin_thi;
    auto intermediate_result_4 = cos(radians(alt_sun[day][t]));
    auto intermediate_result_5 = intermediate_result_2 * intermediate_result_3;
    auto intermediate_result_6 = intermediate_result_1 - intermediate_result_5;
    auto intermediate_result_7 = intermediate_result_6 / intermediate_result_4;
    auto intermediate_result_8 = acos( intermediate_result_7 );
    auto intermediate_result_9 = degrees( intermediate_result_8 );

    bearing_sun[day][t] = intermediate_result_9;
}

This code is much easier to inspect when running the code line by line in a debugger, because you can see the intermediate results.

When I reach the line

auto intermediate_result_8 = acos( intermediate_result_7 );

I can see in the debugger that intermediate_result_7 has the value -1.0009622545441585. Since this is invalid input for the function acos, it will correctly return NaN, so that the final result also is NaN, which is converted to an int, which invokes undefined behavior. This explains the "nonsense negative values" that you mentioned in the question.

Therefore, there appears to be something wrong with the formula that you are using. In order to find the problem, you will have to run the program line by line in a debugger, checking the values of all of the intermediate results.

CodePudding user response:

A rouding error that only affected the calculation when the value was close to the limits of what acos() can accept (between -1 and 1), returning a NaN, invoking undefined behaviour once converted to an int.

  • Related