Гольф кода: формула Leibniz для Pi

Предупреждение: Деление на ноль

Предупреждающее сообщение «Подразделение на ноль» является одним из наиболее часто задаваемых вопросов среди новых разработчиков PHP. Эта ошибка не вызовет исключения, поэтому некоторые разработчики будут иногда подавлять предупреждение, добавляя оператор подавления ошибок @ перед выражением. Например:

$value = @(2 / 0);

Но, как и при любом предупреждении, наилучшим подходом было бы отслеживать причину предупреждения и разрешать его. Причина предупреждения будет происходить из любого экземпляра, где вы пытаетесь разделить на 0, переменную, равную 0, или переменную, которая не была назначена (поскольку NULL == 0), потому что результат будет «неопределенным».

Чтобы исправить это предупреждение, вы должны переписать свое выражение, чтобы проверить, что значение не равно 0, если оно есть, сделать что-то еще. Если значение равно нулю, вы не должны делиться или изменять значение на 1, а затем делить так, что деление приводит к эквиваленту того, что он разделен только дополнительной переменной.

if ( $var1 == 0 ) { // check if var1 equals zero
    $var1 = 1; // var1 equaled zero so change var1 to equal one instead
    $var3 = ($var2 / $var1); // divide var1/var2 ie. 1/1
} else {
    $var3 = ($var2 / $var1); // if var1 does not equal zero, divide
}

Вопросы, относящиеся:

31
задан 7 revs, 5 users 61% 23 May 2017 в 11:48
поделиться

43 ответа

C++

double LeibnizPi( double tolerance )
{
    double sum = 1.0;
    for( int plus_div = 5, minus_div = -3, limit = 10 / tolerance; plus_div < limit ; plus_div += 4, minus_div -= 4 )
        sum += 1./plus_div + 1./minus_div;
    return 4 * sum;
}
1
ответ дан 2 revs 27 November 2019 в 21:19
поделиться

После замечания, что

(= (- (/ 4 n)
      (/ 4 (+ n 2)))
   (/ 8 n (+ n 2)))

или, в более знакомой нотации:

4    4      8
- - --- = ------
n   n+2   n(n+2)

язык Common LISP, с do* цикл (62 существенных символа):

(do* ((n 1 (+ n 4))
      (p 8/3 (+ p (/ 8 n (+ n 2)))))
     ((< (- pi p) 1e-6)
      p)

с рекурсивной функцией хвоста (70 существенных символов):

(defun l (n p)
  (if (< (- pi p) 1e-6)
      p
      (l (+ n 4)
          (+ p (/ 8 n (+ n 2))))))
(l 1 0)

и с расширенным циклом (86 существенных символов):

(loop for n from 1 by 4
      sum (/ 8 n (+ n 2)) into p
      until (< (- pi p) 1e-6)
      finally (return p))

все под предположением, что предварительные проверки, как далеко мы должны пойти для получения желаемой точности, обманывают.

1
ответ дан 2 revs 27 November 2019 в 21:19
поделиться
double d = 1;
double s = 1;
double pi = 0;

while(4.0 / d > 0.000001){
    pi += s*4.0/d;
    d+=2;
    s = -s;        
}
printf("%f\n", pi);
1
ответ дан Maykie 27 November 2019 в 21:19
поделиться

VB 117 символов :

Function Pi()
  Dim t = 0D
  For n = 0 To 1000000
    t += Math.Pow(-1, n) / (2 * n + 1)
  Next
  Return 4 * t
End Function

символы VB LINQ 115 (опускающий ненужное продолжение строки) :

Function Pi()
  Return 4 * Enumerable.Range(0, 1000000) _
             .Sum(Function(n) Math.Pow(-1, n) / (2 * n + 1))
End Function

И затем звоните:

Sub Main()
  Console.WriteLine("{0:n5}", Pi)
End Sub
0
ответ дан BenAlabaster 27 November 2019 в 21:19
поделиться

Другое решение VB, с помощью довольно прохладного синтаксиса агрегирования:

Public ReadOnly Pi As Double = 4 * Aggregate i In Enumerable.Range(0, 100000) _
                                   Select (-1) ^ i / (i * 2 + 1) Into Sum()

Выражение только: 74 символа без ненужных пробелов.

0
ответ дан Konrad Rudolph 27 November 2019 в 21:19
поделиться

Здесь является моим в C++, вероятно, самый длинный способ сделать его: P

double pi(){
   bool add = true;
   double rPi = 0;
   for(long i = 1; i < 99999999; i=i+2)
   {
            double y = (double) i;
            double x = (double) 1;
            if(add)
            {
                   rPi = rPi + (x/y);
                   add = false;
            }
            else
            {
                    rPi = rPi - (x/y);
                    add = true;
            }
   }
            return (rPi * (double) 4);
   }
0
ответ дан teishu 27 November 2019 в 21:19
поделиться

Я просто вид записал это право после того, чтобы читать вопрос об интервью в теме на спорном мнении. Это не симпатично, но мне потребовались приблизительно 3-4 минуты, и я проверяю на точность в каждом цикле. C++. Я проснусь завтра и отправлю решение, которое не сосет:)

double get_pi(int acc)
{

  double pi;
  double dynamicpart;
  int operationCoeff = 1;
  int denom = 3;
  while(1)
  { 
      dynamicpart =
         1/denom + operationCoeff*(denom+2);
      pi = 4*(1-dynamicpart);
      if(!(pi*acc*10-(int)pi*acc*10)) break;
)
      denom+=2;
      operationCoeff = -operationCoeff;
  }



}
0
ответ дан mannicken 27 November 2019 в 21:19
поделиться

Erlang, ~126 символов:

-module (pi).
-export ([pi/0]).

pi() -> 4 * pi(0,1,1).
pi(T,M,D) ->
    A = 1 / D,
    if A > 0.00001 
              -> pi(T+(M*A), M*-1, D+2);
        true  -> T
    end.
0
ответ дан 2 revs 27 November 2019 в 21:19
поделиться

Эээ .... как правило, при обработке чисел следует суммировать ряды от наименьшего члена к наибольшему, чтобы избежать проблем с потерей точности. Итак, в

fortran77

урезано (248 символов)

      function pi(n)
      pi=0.
      t=10**(-n-0.5)
      i=int(4/t)
      i=i/2
      s=-1.                     
      do 1 j=i*2+1,1,-2
         pi = pi + s/j
         s=-s
 1    continue
      pi=abs(pi)*4              
      return
      end

С шаблоном и комментариями (600 символов)

      program leibnitz

      n=5
      p=int(pi(n)*10.**n)/10.**n
      write(6,*)p 

      stop
      end

c     Returns pi computed to <n> digits by the leibniz formula
      function pi(n)
      pi=0.
c     find the smallest term we need by insuring that it is too small to
c     effect the interesting digits.
      t=10**(-n-0.5)
      i=int(4/t)
      i=i/2
      s=-1.                     ! sign of term, might be off by one, but
      do 1 j=i*2+1,1,-2
         pi = pi + s/j
         s=-s
 1    continue
      pi=abs(pi)*4              ! we fix the sign problem here
      return
      end

вывод:

   3.1415901

Кажется, он работает для произвольного количества цифр до 6 знаков, где точность из вещественных заканчивается. Он не оптимизирован для скорости или минимального количества операций.

0
ответ дан 27 November 2019 в 21:19
поделиться

Java

void pi(){
    double x=1,y=1,d=1;
    for(;x<1E6;) { y=-y;d+=y/((2*x++)+1); }
    System.out.println(d*4);
}
0
ответ дан 27 November 2019 в 21:19
поделиться

Python 3 (40 байт)

sum(8/(n*(n+2))for n in range(1,5**8,4))

В этой версии используется оптимизация из @ Svante answer .

print +7 байт

print(sum(8/(n*(n+2))for n in range(1,5**8,4)))

Python 2.x +1 byte

sum(8./(n*(n+2))for n in range(1,5**8,4))

print +6 bytes

print sum(8./(n*(n+2))for n in range(1,5**8,4))

http://codepad.org/amtxUxKp

0
ответ дан 27 November 2019 в 21:19
поделиться

1 символ: . Написано в "MySuperDuperDomainSpecificLanguageThatOnlyReturnsThisOneAnswerAndNothingElse".

Да, это шутка, но серьезно, если вы не запретите DSL, КАЖДЫЙ конкурс Code Golf может быть выигран каким-нибудь губером, который пишет на своем языке, который использует один символ для возврата только одного результата. ..

-1
ответ дан 27 November 2019 в 21:19
поделиться

Lua, 46 символов

p=4 for i=3,9^6,4 do p=p-8/i/(i+2)end print(p)
0
ответ дан 27 November 2019 в 21:19
поделиться
Другие вопросы по тегам:

Похожие вопросы: