On Monday, 25 March 2024 at 14:02:08 UTC, rkompass wrote:

Of course you may also combine the up(+) and down(-) step to one:

1/i - 1/(i+2) = 2/(i*(i+2))

```d
double leibniz(int iter) {
  double n = 0.0;
  for (int i = 1; i < iter; i+=4)
    n += 2.0 / (i * (i+2.0));
  return n * 4.0;
}
```
or even combine both approaches. But of, course mathematically much more is possible. This was not about approximating pi as fast as possible...

The above first approach still works with the original speed, only makes the result a little bit nicer.

It's obvious that you are a good mathematician. You used sequence A005563. First of all, I must apologize to the questioner for digressing from the topic. But I saw that there is a calculation difference between real and double. My goal was to see if there would be a change in speed. For example, with 250 million cycles (iter/4) I got the following result:

3.14159265158976691 (250 5million (with real)
3.14159264457621568 (250 million with double)
3.14159265358979324 (std.math.constants.PI)

First of all, my question is: Why do we see this calculation error with double? Could the changes I made to the algorithm have caused this? Here's an executable code snippet:

```d
enum step = 4;
enum loop = 250_000_000;

auto leibniz(T)(int iter)
{
  T n = 2/3.0;
  for(int i = 5; i < iter; i += step)
  {
    T a = (2.0 + i) * i; // https://oeis.org/A005563
    n += 2/a;
  }
  return n * step;
}

import std.stdio : writefln;

void main()
{
  enum iter = loop * step-10;
  
  65358979323.writefln!"Compare.%s";

  iter.leibniz!double.writefln!"%.17f (double)";
  iter.leibniz!real.writefln!"%.17f (real)";

  imported!"std.math".PI.writefln!"%.17f (enum)";
} /* Prints:

Compare.65358979323
3.14159264457621568 (double)
3.14159265158976689 (real)
3.14159265358979324 (enum)
*/
```

In fact, there are algorithms that calculate accurately up to 12 decimal places with fewer cycles. (e.g. 9999)

SDB@79

Reply via email to