1

I am a real beginner here and I'm really not sure about this. It is a homework assignment.

We have to find 10 (x,y) coordinates of an arc using the radius, a starting angle and an end angle. The program works, but the results it gives differ very slightly from the 'correct' results as required by the automatic checking system. Here's the code and both mine and the systems results based on r=100, angle1=1, anglef=30!

Thanks in advance!

FILE *pf1;  
int n=0;
double angulo1, angulof, angulo, radio, x, y;

printf ("\nIntroduce radio : ");
scanf ("%lf", &radio);
printf ("\nIntroduce angulo inicial :  ");
scanf ("%lf", &angulo1);
printf ("\nIntroduce angulo final : ");
scanf ("%lf", &angulof);

angulo = ((angulof-angulo1)/9);
pf1 = fopen("salida.txt", "w");
for (n=0; n<=9; n++)
{
    x=radio*cos(angulo1+(angulo*n));
    y=radio*sin(angulo1+(angulo*n));    

    fprintf (pf1, "%lf,%lf\n", x,y);
}   
return 0;

.

ERROR
■■■ MY FILE:
54.030231,84.147098
-41.614684,90.929743
-98.999250,14.112001
-65.364362,-75.680250
28.366219,-95.892427
96.017029,-27.941550
75.390225,65.698660
-14.550003,98.935825
-91.113026,41.211849
-83.907153,-54.402111

■■■ CORRECT FILE:
54.030231,84.147095
-41.614685,90.929741
-98.999252,14.112000
-65.364365,-75.680252
28.366219,-95.892426
96.017029,-27.941549
75.390228,65.698662
-14.550003,98.935822
-91.113029,41.211849
-83.907150,-54.402111
JohanC
  • 71,591
  • 8
  • 33
  • 66
  • 2
    What happens if you change `double` to `float`? – the busybee Dec 21 '19 at 16:28
  • 1
    Floating point calculations are rarely exact. This is because of their implementation. You might like to search for this issue, there are lots of resources, also here on StackOverflow. BTW, who says that the correct values have to be like that? – the busybee Dec 21 '19 at 16:30
  • 4
    The checker program is flawed, or it is being used in a way that exceeds its design characteristics. It is almost never appropriate to compare computed floating-point numbers for exact equality. – John Bollinger Dec 21 '19 at 16:36
  • 2
    Details of the data types involved, the specific operations performed, the order of operations, implementation details of the libraries involved, specifics of the floating-point hardware used, compilation options, and probably other things *all* can make differences (usually, but not always, small) in the results. Some of those are mooted by using the an automated solution checker to standardize relevant details, but not all of them. – John Bollinger Dec 21 '19 at 16:40
  • 2
    I would be inclined to take this to my instructor, but if that's not feasible then the only solution I see is to try twiddling details of the computation to hit on the combination that makes the results exactly match. That would be most tedious, and not certain to be successful. – John Bollinger Dec 21 '19 at 16:44
  • 1
    Maybe you should declare the variables as `long doube` to get more precise results. You need to change the respective conversion specifiers then too. – RobertS supports Monica Cellio Dec 21 '19 at 16:52
  • 1
    Perhaps the *instructor* was using `float`. Many of them still teach `float`, from out-of-date teaching material. But anyway, you might benefit from these links: [Is floating point math broken?](http://stackoverflow.com/questions/588004/is-floating-point-math-broken) and [Why Are Floating Point Numbers Inaccurate?](https://stackoverflow.com/questions/21895756/why-are-floating-point-numbers-inaccurate) One way you might improve the accuracy is to divide by `9` last, after the multiplication. So that would be `n * (angulof - angulo1) / 9)`. – Weather Vane Dec 21 '19 at 17:15
  • Thanks John, I have emailed the instructor. But given the dates there's no guarantee he'll get back to me for a couple of weeks. I really appreciate all of your comments! I shall try looking at those links too Weather Vane! – Theo Clarke Dec 21 '19 at 19:13
  • I'll also look at doing the long double too, RobertS, but I have to change the printf output for that right? Since, when I did it before it just turned out zeros. – Theo Clarke Dec 21 '19 at 19:14
  • 1
    @TheoClarke a tip for a new contributor: if you put @ before the username (one per comment) they will get pinged. Otherwise they have to remember to return to the page for a look. – Weather Vane Dec 21 '19 at 19:57
  • 1
    @Weather Vane - Got it! Thanks! – Theo Clarke Dec 21 '19 at 20:15

2 Answers2

1

The post is very confusing:

  • Calculating angles from 1 to 30 radians in 10 steps doesn't make much sense. Sensible values for radians are from -2π to +2π, outside that range trigonomic functions quickly lose precision. Also, making steps that are much larger than a few degrees is very unusual. To get from 1 to 30 radians in 10 steps, steps of almost 180° are taken.
  • Some testing of the output reveals that the steps are smaller: from 1 to 10 radians in 10 steps. This is still 57° per step, and goes almost 2 times around the circle.

Reverse engineering the output with atan2(y,x) reveals that the desired output is less precise than the calculation with doubles. So, probably the calculations used 32 bit floats. To test this, one has to be very careful. Internally, floats can get passed as doubles, and the processor works with 80 bits of precision for arithmetic calculations. (Note that on most machines long double has the same precision as double.)

Now, if you call sin on a float, the compiler often calls the double version of sin. To force the float version, one can try to explicitly call them, they have an f appended to the function name: sinf and cosf.

Testing the following with MicroSoft Visual C, 2017 community edition:

#include <math.h>

void test_sinf()
{
    float radio = 100;
    float angulo1 = 1;
    float angulof = 10;
    float angulo = (angulof - angulo1) / 9;
    float x, y;
    int n;

    for (n = 0; n < 10; ++n) {
        x = radio * cosf(angulo1 + (angulo*n));
        y = radio * sinf(angulo1 + (angulo*n));
        printf("%.6lf,%.6lf\n", x, y);
    }   
}

outputs:

54.030228, 84.147095
-41.614685, 90.929741
-98.999252, 14.112000
-65.364365, -75.680252
28.366220, -95.892426
96.017029, -27.941549
75.390228, 65.698662
-14.550003, 98.935822
-91.113022, 41.211849
-83.907150, -54.402115

This leaves the last digit of only 4 of the numbers with a difference. Which suggests a slightly different library/compiler has been used. As the angles and the radius are all integer numbers which can be represented exact with floats, they are an unprobable cause of the differences.

edit: Testing out the suggestion of @gnasher729 is seems he's right. Running the code with the double precision sin and cos, and convering the result to float before printing, gives exactly the "desired" numbers. This probably gives the same results on most compilers for this test case. (32 bit floats are an IEEE standard, and 64 bit trigonomic functions have enough precision to make implementation details disappear after rounding.)

#include <math.h>

void test_sin_converted_to_float()
{
    float radio = 100;
    float angulo1 = 1;
    float angulof = 10;
    float angulo = (angulof - angulo1) / 9;
    float x, y;

    for (int n = 0; n <= 9; ++n) {
        x = radio * cos(angulo1 + (angulo*n));
        y = radio * sin(angulo1 + (angulo*n));
        printf("%.6lf, %.6lf\n", x, y);
    }   
}
JohanC
  • 71,591
  • 8
  • 33
  • 66
  • Whoever produced the second table could have used any combination of float and double. I suspect sin and cos was used instead of sinf/cosf. – gnasher729 Dec 21 '19 at 23:04
  • You nailed it ! – JohanC Dec 21 '19 at 23:42
  • @JohanC! Thanks! I unfortunately cannot control the radian input, that's given by the automatic correction platform I agree that it's unusual. It changes, not randomly but there are about half a dozen inputs that it cycles through. I really appreciate your thoughts and time. I'm yet to be able to get the automatic checking program to accept it, but I'm going to keep trying. Thanks again. – Theo Clarke Dec 22 '19 at 00:55
1

Checking your data with a spreadsheet, it contains exactly what it ought to contain. The data in the second file however look like sine and cosine where calculated with single precision (float).

Which would mean that whoever created this "automatic checking" should be very, very, ashamed of themselves.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • ! Thanks a lot. It's really good of you to check the data, I really do appreciate it! I have tactfully asked the person who created the automatic checking system to look into it! – Theo Clarke Dec 22 '19 at 00:58
  • The instructor who created the checking program has now removed this exercise from it. So, it seems they are feeling ashamed of themselves right now. – Theo Clarke Dec 22 '19 at 10:34