Гольф кода: формула 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 ответа

Дж, 14 символов

4*-/%>:+:i.1e6
<час>

Объяснение

  • 1e6 является номером 1, сопровождаемым 6, обнуляет (1000000).
  • i.y генерирует первое y не отрицательные числа.
  • +: функция, которая удваивает каждый элемент в аргументе списка.
  • >: функция, которая увеличивает одним каждым элементом в аргументе списка.

Так, выражение >:+:i.1e6 генерирует первый один миллион нечетных чисел:

1 3 5 7...

  • % взаимный оператор (числитель "1" может быть опущен).
  • -/ делает альтернативную сумму каждого элемента в аргументе списка.

Так, выражение -/%>:+:i.1e6 генерирует альтернативную сумму обратных величин первого одного миллиона нечетных чисел:

1 - 1/3 + 1/5 - 1/7 +...

  • 4* умножение четыре. Если Вы умножаетесь на четыре предыдущая сумма, у Вас есть ПЂ.

Вот именно! J является мощным языком для математики.

<час>

Редактирование : начиная с генерации 9! (362880) условия за альтернативную сумму достаточны для имения 5 точности десятичной цифры, и так как формула Leibniz может быть записана также этот путь:

4 - 4/3 + 4/5 - 4/7 +...

... можно записать более короткое, 12 символов версия программы:

-/4%>:+:i.9!
61
ответ дан 7 revs, 3 users 72% 27 November 2019 в 21:19
поделиться

Ruby:

irb(main):031:0> 4*(1..10000).inject {|s,x| s+(-1)**(x+1)*1.0/(2*x-1)}
=> 3.14149265359003
1
ответ дан derobert 27 November 2019 в 21:19
поделиться

64 символа в AWK:

~# awk 'BEGIN {p=1;for(i=3;i<10^6;i+=4){p=p-1/i+1/(i+2)}print p*4}'
3.14159
1
ответ дан LoranceStinson 27 November 2019 в 21:19
поделиться

обман C# - 50 символов :

static single Pi(){
  return Math.Round(Math.PI, 5));
}

Это только говорит "принятие во внимание, что формула пишет функцию...", это не говорит, воспроизводят формулу программно:) Думают вне поля...

C# LINQ - 78 символов :

static double pi = 4 * Enumerable.Range(0, 1000000)
               .Sum(n => Math.Pow(-1, n) / (2 * n + 1));

Альтернатива C# LINQ - 94 символа :

static double pi = return 4 * (from n in Enumerable.Range(0, 1000000)
                               select Math.Pow(-1, n) / (2 * n + 1)).Sum();

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

обычное письмо C# - 89 символов (не считающий необязательные пробелы) :

static double pi()
{
  var t = 0D;
  for (int n = 0; n < 1e6; t += Math.Pow(-1, n) / (2 * n + 1), n++) ;
  return 4 * t;
}
1
ответ дан 9 revs 27 November 2019 в 21:19
поделиться
#!/usr/bin/env python
from math import *
denom = 1.0
imm = 0.0
sgn = 1
it = 0
for i in xrange(0, int(1e6)):
    imm += (sgn*1/denom)
    denom += 2
    sgn *= -1    
print str(4*imm)
1
ответ дан 3 revs 27 November 2019 в 21:19
поделиться

Язык: dc, Символьное количество: 35

dc -e '9k0 1[d4r/r2+sar-lad274899>b]dsbxrp'
2
ответ дан 2 revs 27 November 2019 в 21:19
поделиться

Язык: C99 (неявный возврат 0), Символьное количество: 99 (95 + 4 требуемых пространства)

условие выхода зависит от текущего значения, не от уплотненной версии

#include<stdio.h>
float
p,s=4,d=1;int
main(void){for(;4/d>1E-5;d+=2)p-=(s=-s)/d;printf("%g\n",p);}
фиксированного количества

#include <stdio.h>

float p, s=4, d=1;
int main(void) {
  for (; 4/d > 1E-5; d += 2)
        p -= (s = -s) / d;
  printf("%g\n", p);
}

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

Большинство текущих ответов предполагает, что они получат 5 точности цифр в некотором количестве повторений, и это число является hardcoded в программу. Мое понимание вопроса было то, что сама программа, как предполагается, выясняет, когда это имеет ответ с точностью до 5 цифр и остановки там. На том предположении вот мое решение C#. Я не потрудился минимизировать количество символов, так как нет никакого способа, которым оно уже может конкурировать с некоторыми ответами там, таким образом, я думал, что сделаю его читаемым вместо этого.:)

    private static double GetPi()
    {
        double acc = 1, sign = -1, lastCheck = 0;

        for (double div = 3; ; div += 2, sign *= -1)
        {
            acc += sign / div;

            double currPi = acc * 4;
            double currCheck = Math.Round(currPi, 5);

            if (currCheck == lastCheck)
                return currPi;

            lastCheck = currCheck;
        }
    }
2
ответ дан 2 revs, 2 users 97% 27 November 2019 в 21:19
поделиться

Вот рекурсивный ответ с помощью C#. Это будет только работать с помощью x64 JIT в режиме Release, потому что это - единственный JIT, который применяет оптимизацию последнего вызова, и поскольку ряд сходится так медленно, это приведет к StackOverflowException без него.

было бы хорошо иметь эти IteratePi функция как анонимная лямбда, но поскольку это саморекурсивно, мы должны были бы начать делать весь способ ужасных вещей с Y-combinators, таким образом, я оставил его как отдельную функцию.

public static double CalculatePi()
{
    return IteratePi(0.0, 1.0, true);
}

private static double IteratePi(double result, double denom, bool add)
{
    var term = 4.0 / denom;
    if (term < 0.00001) return result;    
    var next = add ? result + term : result - term;
    return IteratePi(next, denom + 2.0, !add);
}
2
ответ дан Greg Beech 27 November 2019 в 21:19
поделиться

Язык: Brainfuck, Символьное количество: 51/59

Проводит этот подсчет? =]

, поскольку нет никаких чисел с плавающей запятой в Brainfuck, было довольно трудно получить подразделения, работающие правильно. Grr.

Без новой строки (51):

+++++++[>+++++++<-]>++.-----.+++.+++.---.++++.++++.

С новой строкой (59):

+++++++[>+++++++>+<<-]>++.-----.+++.+++.---.++++.++++.>+++.
37
ответ дан 2 revs, 2 users 97% 27 November 2019 в 21:19
поделиться

Символы Perl

26

26 просто функция, 27 для вычисления, 31 для печати. От комментариев до этот ответ .

sub _{$-++<1e6&&4/$-++-&_}       # just the sub
sub _{$-++<1e6&&4/$-++-&_}_      # compute
sub _{$-++<1e6&&4/$-++-&_}say _  # print

28 символов

28 просто вычислений, 34 для печати. Из комментариев. Обратите внимание, что эта версия не может использовать, 'говорят'.

$.=.5;$\=2/$.++-$\for 1..1e6        # no print
$.=.5;$\=2/$.++-$\for$...1e6;print  # do print, with bonus obfuscation

36 символов

36 просто вычислений, 42 для печати. Взятие Гудзона при перестановке dreeves, из комментариев.

$/++;$\+=8/$//($/+2),$/+=4for$/..1e6
$/++;$\+=8/$//($/+2),$/+=4for$/..1e6;print

Об итеративном количестве: насколько мои математические памяти идут, 400000 доказуемо достаточно, чтобы быть с точностью до 0,00001. Но миллион (или настолько же низко как 8e5) на самом деле заставляет десятичное расширение на самом деле соответствовать 5 дробным местам, и это - тот же счетчик символов, таким образом, я сохранил это.

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

Ruby, 33 символа

(0..1e6).inject{|a,b|2/(0.5-b)-a}
23
ответ дан 4 revs 27 November 2019 в 21:19
поделиться

Другая версия C#:

(60 символов)

4*Enumerable.Range(0, 500000).Sum(x => Math.Pow(-1, x)/(2*x + 1));  // = 3,14159
20
ответ дан 2 revs 27 November 2019 в 21:19
поделиться

52 символа в Python :

print 4*sum(((-1.)**i/(2*i+1)for i in xrange(5**8)))

(51 отбрасывание 'x' от xrange.)

36 символов в Октаве (или Matlab):

l=0:5^8;disp((-1).^l*(4./(2.*l+1))')

(выполняют "формат долго"; показать все значащие цифры.) Опускающий 'disp' мы достигаем 30 символов:

octave:5> l=0:5^8;(-1).^l*(4./(2.*l+1))'
ans = 3.14159009359631
14
ответ дан 7 revs, 3 users 83% 27 November 2019 в 21:19
поделиться

символы Oracle SQL 73

select -4*sum(power(-1,level)/(level*2-1)) from dual connect by level<1e6
13
ответ дан 2 revs, 2 users 89% 27 November 2019 в 21:19
поделиться

Язык: C, Символьное количество: 71

float p;main(i){for(i=1;1E6/i>5;i+=2)p-=(i%4-2)*4./i;printf("%g\n",p);}

Язык: C99, Символьное количество: 97 (включая необходимую новую строку)

#include <stdio.h>
float p;int main(){for(int i=1;1E6/i>5;i+=2)p-=(i%4-2)*4./i;printf("%g\n",p);}

я должен отметить, что вышеупомянутые версии (которые являются тем же) отслеживают то, влияло ли дополнительное повторение на результат вообще. Таким образом это выполняет минимальное количество операций. Для добавления большего количества цифр замените 1E6 1E(num_digits+1) или 4E5 с 4E(num_digits) (в зависимости от версии). Для полных программ, %g, возможно, должен быть заменен. float, возможно, должен быть изменен на [1 110] также.

Язык: C, Символьное количество: 67 (см. примечания)

double p,i=1;main(){for(;i<1E6;i+=4)p+=8/i/(i+2);printf("%g\n",p);}

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

Язык: C, Символьное количество: 24 (обман )

main(){puts("3.14159");}

не работает с количествами цифры> 6, все же.

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

Haskell

я свалил его к 34 символам:

foldl subtract 4$map(4/)[3,5..9^6]

Это выражение уступает 3.141596416935556, когда оценено.

Редактирование: вот несколько более короткая версия (в 33 символах), который использует foldl1 вместо foldl:

foldl1 subtract$map(4/)[1,3..9^6]

Редактирование 2: 9^6 вместо 10^6. Нужно быть экономичным;)

Редактирование 3: Замененный foldl' и foldl1' с foldl и foldl1 respectively— в результате Редактирования 2, это больше не переполняется. Благодаря ShreevatsaR для того, чтобы замечать это.

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

23 символа в MATLAB:

a=1e6;sum(4./(1-a:4:a))
10
ответ дан gnovice 27 November 2019 в 21:19
поделиться

F#:

Попытка № 1:

let pi = 3.14159

Обман? Нет, его победа со стилем!

Попытка № 2:


let pi =
    seq { 0 .. 100 }
    |> Seq.map (fun x -> float x)
    |> Seq.fold (fun x y -> x + (Math.Pow(-1.0, y)/(2.0 * y + 1.0))) 0.0
    |> (fun x -> x * 4.0)

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

9
ответ дан 2 revs, 2 users 97% 27 November 2019 в 21:19
поделиться

язык Common LISP, 55 символов.

(loop for i from 1 upto 4e5 by 4 sum (/ 8d0 i (+ i 2)))
7
ответ дан user49117 27 November 2019 в 21:19
поделиться

Mathematica, 27 символов (возможно всего 26 или целых 33)

NSum[8/i/(i+2),{i,1,9^9,4}]

при удалении начальной буквы "N" тогда она дает ответ как (огромную) часть.

, Если это обманывает тот Mathematica, не нуждается в операторе печати для вывода его результата, тогда предварительно ожидают" Print@" для в общей сложности 33 символов.

нбар:

, Если это обманывает к hardcode количество условий, тогда я не думаю, что любой ответ все же разобрался в этом. Проверка, когда текущий термин ниже некоторого порога, является не лучше, чем жесткое кодирование количеством условий. Просто, потому что текущий термин только изменяется, 6-я или 7-я цифра не означает, что сумма достаточного количества последующих условий не изменит 5-ю цифру.

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

Используя формулу для остаточного члена в переменном ряду (и таким образом необходимое количество повторений для достижения желаемой точности трудно не кодируется в программу):

public static void Main(string[] args) {
    double tolerance = 0.000001;
    double piApproximation = LeibnizPi(tolerance);
    Console.WriteLine(piApproximation);
}

private static double LeibnizPi(double tolerance) {
    double quarterPiApproximation = 0;

    int index = 1;
    double term;
    int sign = 1;
    do {
        term = 1.0 / (2 * index - 1);
        quarterPiApproximation += ((double)sign) * term;
        index++;
        sign = -sign;
    } while (term > tolerance);

    return 4 * quarterPiApproximation;
}
5
ответ дан 2 revs 27 November 2019 в 21:19
поделиться

C#:

public static double Pi()
{
    double pi = 0;
    double sign = 1;
    for (int i = 1; i < 500002; i += 2)
    {
        pi += sign / i;
        sign = -sign;
    }
    return 4 * pi;
}
4
ответ дан Darin Dimitrov 27 November 2019 в 21:19
поделиться

Ruby, 41 символ (использующий irb):

s=0;(3..3e6).step(4){|i|s+=8.0/i/(i-2)};s

Или это немного дольше, non-irb версия:

s=0;(3..3e6).step(4){|i|s+=8.0/i/(i-2)};p s

Это - измененный Leibniz:

  1. пары терминов Объединения. Это дает Вам 2/3 + 2/35 + 2/99 +...
  2. Pi становится 8 * (1 / (1 * 3) + 1 / (5 * 7) + 1 / (9 * 11) +...)
4
ответ дан zenazn 27 November 2019 в 21:19
поделиться

(интерактивный режим) F# (59 Символов)

{0.0..1E6}|>Seq.fold(fun a x->a+ -1.**x/(2.*x+1.))0.|>(*)4.

(Урожаи предупреждение, но опускает броски)

4
ответ дан 2 revs, 2 users 73% 27 November 2019 в 21:19
поделиться

C# с помощью блока итератора:

static IEnumerable<double> Pi()
{
    double i = 4, j = 1, k = 4;
    for (;;)
    {
        yield return k;
        k += (i *= -1) / (j += 2);
    }
}
3
ответ дан dalle 27 November 2019 в 21:19
поделиться

Вот решение в MUMPS.

pi(N)
 N X,I
 S X=1 F I=3:4:N-2 S X=X-(1/I)+(1/(I+2))
 Q 4*X

Параметр N указывает сколько повторных частей для использования. Таким образом, если Вы передадите в 5, то это оценит 4 * (1 - 1/3 + 1/5 - 1/7 + 1/9 - 1/11)

, Некоторое эмпирическое тестирование показало, что N=272241 является самым низким значением, которое дает правильное значение 3,14159, когда усеченный к 5 десятичным точкам. Необходимо перейти к N=852365 для получения значения, которое округляется к 3,14159.

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

Для записи эта реализация Схемы имеет 95 символов, игнорирующих ненужный пробел.

(define (f)
  (define (p a b)
    (if (> a b)
      0
      (+ (/ 1.0 (* a (+ a 2))) (p (+ a 4) b))))
  (* 8 (p 1 1e6)))
3
ответ дан Alan 27 November 2019 в 21:19
поделиться

JavaScript:

a=0,b=-1,d=-4,c=1e6;while(c--)a+=(d=-d)/(b+=2)

В JavaScript. 51 символ. Очевидно, не собираясь побеждать, но а.: Редактирование P

- обновленный, чтобы быть 46 символами теперь, благодаря Strager.:)

<час>

ОБНОВЛЕНИЕ (30 марта 2010)

А быстрее (точный [только 114] к 5 десятичным разрядам) 43 символьных версии David Murdoch

for(a=0,b=1,d=4,c=~4e5;++c;d=-d)a-=d/(b-=2)
3
ответ дан 5 revs, 2 users 62% 27 November 2019 в 21:19
поделиться

Perl:

$i+=($_&1?4:-4)/($_*2-1)for 1..1e6;print$i

для в общей сложности 42 символов.

4
ответ дан Learning 27 November 2019 в 21:19
поделиться
Другие вопросы по тегам:

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