1. Pascal / Говнокод #5027

    +99

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    Procedure MakeChain(x: real; var a: array of word); (* Процедура раскладывает вещественное число в цепную дробь *)
      var 
        i: byte;
      begin
        i:=0;
        Repeat
          a[i]:=Int(x); x:=1/(x-a[i]); i:=i+1
        Until (abs(1/x) < epsilon) or (Int(x) = 0) (* NB! *)
      end;
    Procedure MakeFrac(a: array of word; var AN, BN: word); (* Процедура собирает обыкновенную дробь из цепной дроби *)
      var
        i: byte; AP, BP: word; temp: word;
      begin
        AN:=1; AP:=0; BN:=a[1]; BP:=1; i:=2;
        Repeat
          temp:=AN; AN:=AN*a[i]+AP; AP:=temp;
          temp:=BN; BN:=BN*a[i]+BP; BP:=temp;
          i:=i+1
        Until a[i] = 0 (* NB! *)
      end;
    Function PowerInt(x: real; p: longint): real; (* возведение числа в целую степень *)
      var
        R: real;
      begin
        R:=1; if p<0 then x:=1/x; p:=abs(p);
        Repeat
          if p and 1 = 1 then R:=R*x;
          p:=p shr 1;
          if p<>0 then x:=sqr(x)
        Until p=0;
        PowerInt:=R
      end;
    Function Power(x: real; p: real): real;
      var
        y: real;
        z: array[0..16000 div sizeof(word)] of word;
        a, b: word;
      begin
        y:=PowerInt(x, Trunc(p)) * exp(Frac(p) * ln(abs(x)));
        if x<0 then
          begin
            MakeChain(Frac(p), z);
            MakeFrac(z, a, b);
            if Odd(b) then
              begin
                if Odd(a) then y:=-y (* если числитель и знаменатель показателя степени нечётные, меняем знак результата *)
              end
            else
              begin
                (* NB! В случае чётного знаменателя показателя степени результат комплексный. Забьём на это *)
              end	
          end;
        Power:=y
      end;

    Инновационный алгоритм, написанный мной лет 12 тому назад, позволяющий возводить отрицательные числа в дробную степень.
    Жанру сайта вполне соответствует, то есть не без говнокода.

    Запостил: inkanus-gray, 23 Декабря 2010

    Комментарии (10) RSS

    • Секрет успеха говнокода: Не рассказывайте, что Вы это написали сами давно и на лабах.
      Ваш К.О.
      Ответить
      • Благодарю за ценные рекомендации.
        Ответить
      • могу добавить еще один секрет: Короткие говняшки смешнее длинного и скучного кала

        -
        ассистент кэпа
        Ответить
    • А так код веселый. :)

      Особенно здесь:
      z: array[0..16000 div sizeof(word)] of word;
      Ответить
    • <irony>Кто-то поставил минусы, значит это не говнокод. Ушёл патентовать.</irony>

      Веселье, по крайней мере, здесь:
      1. Первые две процедуры можно сшить в одну, и тогда массив больше не нужен.
      2. Нужен более адекватный критерий завершения разложения в цепную дробь. Если a и b становятся большими, продолжать разложение нет смысла.

      Был ещё один вариант 39-й строки:
      y:=PowerInt(exp(1/b * ln(abs(x))), a);
      Ответить
    • а я че т не понял
      > Until (abs(1/x) < epsilon) or (Int(x) = 0)
      Ответить
      • Наверное, надо было наоборот?
        Ответить
        • вообще то второе условие сразу поглощает первое
          Ответить
          • Почему?
            abs(1/x) < epsilon - это значит, что икс по модулю мегабольшое
            Int(x) = 0 - это значит, что икс по модулю меньше 1/2
            Ответить

    Добавить комментарий