# Compute/displaying arbitrary decimal digits

**URL:** <https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968>\
**Category:** Offtopic\
**Created:** [April 17, 2020, 7:49pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968 "2020-04-17T19:49:56Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 17, 2020, 7:49pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/1 "2020-04-17T19:49:56Z")

</div>

I’m trying to compute/display floating point values to at least 100 digits.  
When I run this I only get the following output.

```auto
require "big"

def ramanujan_num(x, digits=32)
    Math.exp(Math::PI * Math.sqrt(x)).significant(digits)
end

digits = 100
#puts "Ramanujan's constant to #{digits} decimals:\n #{ramanujan_num(163, digits)}"
printf("Ramanujan's constant to #{digits} decimals:\n%s\n\n", ramanujan_num(163, digits))

```

```auto
# Produced output:
Ramanujan's constant to 100 decimals:
2.6253741264076826e+17

# Desired output:
Ramanujan's constant to 100 decimals:
262537412640768743.9999999999992500725971981856888793538563373369908627075374103782106479101186073129511813461860645042

```

How do I compute/display the desired output?

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 17, 2020, 8:08pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/2 "2020-04-17T20:08:40Z")

</div>

Two things:

- you can use `%.100f` as a format specifier to format float with 100 decimal places
- I don’t think floats have 100 decimal places
- you `require "big"` but never use it… 🤔

Edit: classic off-by-one error 🤷‍♂️

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 17, 2020, 8:31pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/3 "2020-04-17T20:31:34Z")

</div>

I can display to 100 digits now with the %.100f but the computed value is still wrong.

```auto
printf("Ramanujan's constant to #{digits} decimals:\n%.100f\n\n", ramanujan_num(163, digits))

262537412640766432.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

```

So now I need to do the computation to display to the desired precision.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 17, 2020, 8:51pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/4 "2020-04-17T20:51:03Z")

</div>

Do you know how to do this in another language? That way I could try to see how to do it in Crystal. Ruby gives me the same answer.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 17, 2020, 9:01pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/5 "2020-04-17T21:01:33Z")

</div>

> [@asterite](#):
>
> Do you know how to do this in another language? That way I could try to see how to do it in Crystal. Ruby gives me the same answer

I’m trying to do this Rosetta Code example, mimicking the `Sidef` example.

```auto
# Sidef example and output

func ramanujan_const(x, decimals=32) {
    local Num!PREC = *"#{4*round((Num.pi*√x)/log(10) + decimals + 1)}"
    exp(Num.pi * √x) -> round(-decimals).to_s
}
 
var decimals = 100
printf("Ramanujan's constant to #{decimals} decimals:\n%s\n\n",
     ramanujan_const(163, decimals))
 
say "Heegner numbers yielding 'almost' integers:"
[19, 96, 43, 960, 67, 5280, 163, 640320].each_slice(2, {|h,x|
    var c = ramanujan_const(h, 32)
    var n = (x**3 + 744)
    printf("%3s: %51s ≈ %18s (diff: %s)\n", h, c, n, n-Num(c))
})

# Output
Ramanujan's constant to 100 decimals:
262537412640768743.9999999999992500725971981856888793538563373369908627075374103782106479101186073129511813461860645042

Heegner numbers yielding 'almost' integers:
 19: 885479.77768015431949753789348171962682 ≈ 885480 (diff: 0.22231984568050246210651828037318)
 43: 884736743.99977746603490666193746207858538 ≈ 884736744 (diff: 0.00022253396509333806253792141462)
 67: 147197952743.99999866245422450682926131257863 ≈ 147197952744 (diff: 0.00000133754577549317073868742137)
163: 262537412640768743.99999999999925007259719818568888 ≈ 262537412640768744 (diff: 0.00000000000074992740280181431112)

```

Crystal code and output.

```auto
def ramanujan_num(x, digits=32)
  #(Math::E ** (Math::PI * Math.sqrt(x)) )
  (Math.exp(Math::PI * Math.sqrt(x))).round(digits)
end

digits = 100
#puts "Ramanujan's constant to #{digits} decimals:\n #{ramanujan_num(163, digits)}"
#printf("Ramanujan's constant to #{digits} decimals:\n%s\n\n", ramanujan_num(163, digits))
printf("Ramanujan's constant to #{digits} decimals:\n%s\n\n", ramanujan_num(163, digits))
 
puts "Heegner numbers yielding 'almost' integers:"
[19, 96, 43, 960, 67, 5280, 163, 640320].each_slice(2) { |(h, x)|
  c = ramanujan_num(h, 32)
  n = (x**3 + 744)
  printf("%3s: %51s ≈ %18s (diff: %s)\n", h, c, n, n-c)
}

Ramanujan's constant to 100 decimals:
2.6253741264076826e+17

Heegner numbers yielding 'almost' integers:
 19: 885479.7776801554 ≈ 885480 (diff: 0.2223198446445167)
 43: 884736743.9997752 ≈ 884736744 (diff: 0.00022482872009277344)
Unhandled exception: Arithmetic overflow (OverflowError)
  from /home/jzakiya/crystal/share/crystal/src/int.cr:280:14 in '**'
  from ramanujan.cr:16:8 in '__crystal_main'
  from /home/jzakiya/crystal/share/crystal/src/crystal/main.cr:105:5 in 'main_user_code'
  from /home/jzakiya/crystal/share/crystal/src/crystal/main.cr:91:7 in 'main'
  from /home/jzakiya/crystal/share/crystal/src/crystal/main.cr:114:3 in 'main'
  from __libc_start_main
  from ../sysdeps/x86_64/start.S:122:0 in '_start'
  from ???

}

```

I was looking at the docs to see if there’s a way to increase the computational precision.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 17, 2020, 9:15pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/6 "2020-04-17T21:15:12Z")

</div>

[https://trizen.gitbooks.io/sidef-lang/syntax\_and\_semantics/literals/float.html](https://trizen.gitbooks.io/sidef-lang/syntax_and_semantics/literals/float.html)

> In Sidef, all literal numbers are specially parsed and converted implicitly into a rational number, which are internally represented by [Math::GMPz](https://metacpan.org/pod/Math::GMPz) and [Math::GMPq](https://metacpan.org/pod/Math::GMPq).

You will need to use those types in Crystal. I don’t know if we have those, though.

That explains why Sidef has more precision: they simply don’t use the machine Float64 representation, they use rationals.

---

<div class="post-metadata">

**Author:** ![jzakiya](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/jzakiya/32/278_2.png) [@jzakiya](https://forum.crystal-lang.org/u/jzakiya)\
**Post date:** [April 17, 2020, 10:50pm UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/7 "2020-04-17T22:50:50Z")

</div>

Thanks for the research @asterite, I thought it was something like that because they explicitly do a `to_s` on `exp(Num.pi * √x) -> round(-decimals).to_s`.

So I guess Crystal can’t (currently) fulfill the requirements of this task because it can’t compute/display the necessary digits of precision.

---

<div class="post-metadata">

**Author:** ![rogerdpack](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/rogerdpack/32/117_2.png) [@rogerdpack](https://forum.crystal-lang.org/u/rogerdpack)\
**Post date:** [April 18, 2020, 4:54am UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/8 "2020-04-18T04:54:05Z")

</div>

Math.sqrt(x) returns a Float32 I think, maybe it’s not precise enough? [https://crystal-lang.org/api/0.33.0/Math.html#sqrt(value:Float32)-instance-method](https://crystal-lang.org/api/0.33.0/Math.html#sqrt(value:Float32)-instance-method)

---

<div class="post-metadata">

**Author:** ![straight-shoota](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/straight-shoota/32/36_2.png) [@straight-shoota](https://forum.crystal-lang.org/u/straight-shoota)\
**Post date:** [April 18, 2020, 10:15am UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/9 "2020-04-18T10:15:16Z")

</div>

The required precision can only be provided by `Big*` numbers. However, it seems some of the necessary math operations are not yet implemented.

---

<div class="post-metadata">

**Author:** ![asterite](https://yyz2.discourse-cdn.com/flex036/user_avatar/forum.crystal-lang.org/asterite/32/60_2.png) [@asterite](https://forum.crystal-lang.org/u/asterite)\
**Post date:** [April 18, 2020, 11:35am UTC](https://forum.crystal-lang.org/t/compute-displaying-arbitrary-decimal-digits/1968/10 "2020-04-18T11:35:12Z")

</div>

Right. We have BigRational in the standard library. We are just missing some functionality (like exp and PI)
