Занимательная математика или когда возведение в квадрат дает минус.

от
Прочее   математика

Началось все с того что иногда при извлечении квадратного корня начала вылетать ошибка…

Честно говоря, я от этого впал небольшой ступор. Ведь ошибка возникала там, где ее быть в принципе не может. То есть, мне нужно было вычислить расстояние между двумя точками, если кто не в курсе вот формула:

  formula.PNG

Если короче, то ошибка возникнет, только если попытаться извлечь корень из отрицательного числа, что при данном раскладе невозможно (ну если кто в танке, возведение в квадрат, только положительные числа =)).

Собственно вот упрощенный код на дельфи (паскале), где и появлялась ошибка.

  1. var
  2. x1,y1,
  3. x2,y2:integer;
  4. dist:single;
  5. begin
  6.  
  7. x1:=10;
  8. y1:=10;
  9.  
  10. x2:=110;
  11. y2:=46350 + 1;
  12.  
  13. dist:= Sqrt(sqr(x2 - x1) + sqr(y2 - y1));
  14.  
  15. showmessage(floattostr(dist));
  16. end;

Стоит обратить внимание на то, что ошибка не появится, пока координаты точек не превысят определенное значение, то есть ошибка не явная, и отследить ее достаточно трудно.

Дальше пойдут эксперименты. И если кому то лень читать, или вы еще не догадались в чем дело, то знайте =)

Оказывается тупо переполнилась переменная типа integer… Вот так все просто.

Я на это потратил порядка двух часов, пока догадался, да такой я вот не умный =)

Так как, Дельфи (среда Delphi 7) упорно молчит о переполнении переменной, а только указывает, что извлечь корень из отрицательного числа невозможно, посмотрим как поведут себя другие языки программирования.

Все описанные ниже примеры, абстрактны и призваны показать, как можно допустить данную ошибку.

В C++ (среда Dev-C++) стоит только неправильно указать тип результата функции…

  1. int sqr (int arg)  // возведение в квадрат
  2.  {
  3.  return pow(arg,2);      
  4.  }
  5.  
  6. int main(int argc, char *argv[])
  7. {
  8.  
  9.  
  10. int x1 = 10,
  11.     y1 = 10,
  12.     x2 = 110,
  13.     y2 = 46350 + 1;  
  14.  
  15. double dist;  
  16.  
  17. dist = sqrt(sqr(x1 - x2) + sqr (y1 - y2)); //Вычислить расстояние между точками
  18.  
  19. printf("%f\n", dist);      
  20.  
  21.  
  22.     system("PAUSE");
  23.     return EXIT_SUCCESS;
  24. }

В С # (среда Microsoft Visual C# 2010 Express) по сути тоже самое

  1. namespace ConsoleApplication1
  2. {
  3.     class Program
  4.     {
  5.  
  6.         static int sqr(int arg)  // возведение в квадрат
  7.         {
  8.             return arg * arg;
  9.         }
  10.  
  11.  
  12.         static void Main(string[] args)
  13.         {
  14.         int x1 = 10,
  15.             y1 = 10,
  16.             x2 = 110,
  17.             y2 = 46350 + 1;
  18.  
  19.         double dist;
  20.  
  21.         dist = Math.Sqrt(sqr(x1 - x2) + sqr(y1 - y2)); //Вычислить расстояние между точками
  22.  
  23.         Console.WriteLine(dist);
  24.  
  25.         Console.ReadKey();
  26.         }
  27.     }
  28. }


PHP (Среда «Notepad» =))
Не знаю, как в ПХП сделать такую ошибку, интерпретатор сам определяет типы переменных. Хотя было бы желание. Вот пример для наглядности.


  1. <?
  2. function sqr ($arg)
  3.  {
  4.  return (int) pow($arg,2);
  5.  }
  6.  
  7. $x1 = 10.01;
  8. $y1 = 10.4;
  9. $x2 = 110.0;
  10. $y2 = 46350.00 + 1.99;
  11.  
  12. $dist = sqrt(sqr($x1 - $x2) + sqr ($y1 - $y2)); //Вычислить расстояние между точками
  13.  
  14. echo $dist;
  15. ?>


Java Script – с ним все в норме, так как для чисел, там только один тип number

Остальные ЯП мне не очень нравятся, поэтому тут и остановимся. Все это это мои личные изъяснения, и если я не прав, буду рад если кто укажет в чем именно.
-2   0   2
914