pole wielokata

0

Musze napisac program, kotry liczy pole dowolnego wielokata. Napisalem, go na windowsie uzyskuje poprawna odpowiedz niestety na linuxie(spoj) otrzymuje "nan" na wyjsciu.

#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>




typedef struct Point {
   long double x,y;     
   double angle;
};

  
double heron(struct Point *a,struct Point *b,struct Point *c) {
  long double d1,d2,d3,s,p;
  d1=sqrt((a->x-b->x)*(a->x-b->x)+(a->y-b->y)*(a->y-b->y));
  d2=sqrt((a->x-c->x)*(a->x-c->x)+(a->y-c->y)*(a->y-c->y));
  d3=sqrt((b->x-c->x)*(b->x-c->x)+(b->y-c->y)*(b->y-c->y));  
  s=(d1+d2+d3)/2;
  p=sqrt(s*(s-d2)*(s-d1)*(s-d3));
  return p;    
};

double areaSurface(struct Point *a, int n) {
  int i;
  long double s=0;
  for (i=1;i<n-1;i++)
   s+=heron(&a[0],&a[i],&a[i+1]);
   return s;      
};

void angle (struct Point *a,int n) {
    int i=0;
	double angle=0;
	double k=0;
	for(i=1;i<n;++i) {
	
		double x = ((a[0].x)- (a[i].x));
		double y = (a[0].y-a[i].y);
		angle = atan2(y,x)*(180/3,14);
		if(angle < 0) angle+=180;
		a[i].angle = angle;
	};
};


void boublesort(struct Point *a, int size) {
     int i, j;
	
     for (i = 0; i<size; i++)
        for (j=0; j<size-1; j++) {
           if (a[j].angle > a[j+1].angle) {
             double x = a[j+1].x;
			 double y = a[j+1].y;
			 double angle = a[j+1].angle;
             a[j+1] = a[j];
             a[j].x = x;
			 a[j].y = y;
			 a[j].angle = angle;
		  };
      };
};


void boublesort2(struct Point *a, int size) {
     int i, j;
	
     for (i = 0; i<size; i++)
        for (j=0; j<size-1; j++) {
           if (a[j].x > a[j+1].x) {
             double x = a[j+1].x;
			 double y = a[j+1].y;
			 a[j+1] = a[j];
             a[j].x = x;
			 a[j].y = y;
	
		  };
      };
};

int main() {
  int i,n,how,j;
  struct Point a[10];
  char op;

	scanf("%d", &how);
	for (i = 0; i < how; ++i) {
		do scanf("%c", &op);
		while (op != '{');

		for (j = 0; op != '}'; ++j) {
			scanf("{%lf,%lf}", &a[j].x, &a[j].y);
			scanf("%c", &op);
		};
	
		boublesort2(a,j);
		angle(a,j);
		boublesort(a,j);
		printf("%.3lf\n",areaSurface(a,j));  
	};
	return 0;
};


Gdy zmieniam long double na double/floaty to niby juz nie mam nan ale mam za to zle wyjscie.
To wejscie :

5
{{0,1},{1,0},{0,0}}
{{1.5,0},{0,0.5},{3,0.5},{2,2.5},{0,2}}
{{1.5,2.5},{1.5,0.5},{2.5,1.5},{0.5,1.5}}
{{2.5,1},{0,1.5},{2,3},{0.5,0.5},{1,2.5}}
{{-4,3},{2,5},{5,1}}

A to prawidlowe wyjscie :

0.500
5.250
2.000
3.750
15.000
0

Może coś więcej powiesz na temat tego twojego wielokąta.
Zmieniając kolejność wierzchołków wielokąta dostajemy zupełnie inny wielokąt.
Bierzemy kwadrat A,B,C,D zmieniamy kolejność na A,B,D,C wychodzi nam klepsydra która ma o połowę mniejszą powierzchnie.
Przy małych powierzchniach trójkąta równanie herona zawodzi w związku z niedokładnością funkcji sqrt()
Użyj równania wynikającego z iloczynu wektorów:

double triangle_surface(struct Point *a,struct Point *b,struct Point *c)
  {
   return fabs((a->x-c->x)*(b->y-c->y)-(a->y-c->y)*(b->x-c->x))/2;
  }
0

Heron zawodzi również dla dużych trójkątów (przyczyna jest w odejmowaniu bliskich sobie, dużych liczb). Dla trójkąta o bokach
12345678, 12345679 i 1.01233995 pole obliczone przy użyciu float wynosi 0, a przy użyciu double wynosi ponad 900 tysięcy.

1 użytkowników online, w tym zalogowanych: 0, gości: 1