5
\$\begingroup\$

I have written code in Kotlin with the objective of computing Pi in few enough lines so that it looks good on a t-shirt.

Can be cut and paste into http://try.kotlinlang.org under "My Programs" and run from browser - I just tested it with version 1.2.41 and it's working.

import kotlin.math.*
import java.math.BigInteger 
fun main(args: Array<String>) { 
 val r = (4*(4*arccot(5) - arccot(239))).toString()
 println("314 digits of Pi ${r[0]}.${r.substring(1).dropLast(5)}")
}
fun arccot(x:BigInteger):BigInteger {
 var precision = 10.toBigInteger().pow(319) / x
 var total = precision
 var divisor = 1.toBigInteger()
 while(precision.abs() >= divisor) {
 precision = -precision / x.pow(2)
 divisor += 2
 total += precision / divisor
 }
 return total
}
fun arccot(x:Int) = arccot(x.toBigInteger())
operator fun Int.times(x: BigInteger) = this.toBigInteger() * x
operator fun BigInteger.plus(x: Int) = this + x.toBigInteger()

Currently it's longer than I'd like. I would like to shorten without making it less understandable. My vision is to have code that is readable enough it wouldn't be out of place in a production code base.

To give an idea, here's the significantly shorter Python version (which has been printed on a t-shirt and in my opinion looks good and is short enough but also quite readable). Can be run in browser here: https://repl.it/@sek/314-Digits - (there's also a link from there to the t-shirt if you are curious how that looks - the length in question isn't only the number of lines but also the width of the longest line as that determines the font size that can be used)

def pi():
 r = 4*(4*arccot(5) - arccot(239))
 return str(r)[0]+'.'+str(r)[1:-5]
def arccot(x):
 total = power = 10**319 // x
 divisor = 1
 while abs(power) >= divisor:
 power = -power // x**2
 divisor += 2
 total += power // divisor
 return total
print("314 digits of Pi " + pi())
asked May 25, 2018 at 21:23
\$\endgroup\$
1
  • \$\begingroup\$ I'm sorry but that is wrong. Try this. \$\endgroup\$ Commented May 25, 2018 at 22:31

1 Answer 1

3
\$\begingroup\$

I noticed that you are calculating to 314 decimal places instead of 314 digits, so drop 6 instead of 5.

  • You really don't need the extra functions. You can remove

    fun arccot(x:Int) = arccot(x.toBigInteger())
    

    if you convert Int to BigInteger inside your arctan method.

  • You can remove

    operator fun Int.times(x: BigInteger) = this.toBigInteger() * x
    

    if you shl(2) instead of * 4.

  • You can remove

    operator fun BigInteger.plus(x: Int) = this + x.toBigInteger()
    

    if you change

    divisor += 2
    

    to

    divisor += BigInteger("2")
    
  • You can shorten

    println("314 digits of Pi ${r[0]}.${r.substring(1).dropLast(5)}")
    

    to

    println("314 digits of Pi ${r[0]}.${r.substring(1,314)}")
    
  • Now, you can change the imports to

    import java.math.*
    
  • You don't have to declare the type for val r.

The final code I came up with by doing that is:

import java.math.*
fun main(args: Array<String>) {
 val r = (acot(5).shl(2)-acot(239)).shl(2).toString()
 println("314 digits of Pi ${r[0]}.${r.substring(1,314)}")
}
fun acot(x:Int):BigInteger {
 var precision = BigInteger.TEN.pow(319)/x.toBigInteger()
 var total = precision
 var divisor = BigInteger.ONE;
 while(precision.abs() >= divisor) {
 precision = -precision/(x.toBigInteger().pow(2))
 divisor += BigInteger("2")
 total += precision / divisor
 }
 return total
}

I also came up with shorter code, with decreased width, by calculating a different way:

import java.math.*
fun main(args:Array<String>) {
 val b4 = BigDecimal(4)
 val r = ((atan(5)*b4-atan(239))*b4).toString()
 println("314 digits of Pi ${r.substring(0,315)}")
}
fun atan(xInv:Int):BigDecimal {
 var x = BigDecimal(1).divide(BigDecimal(xInv),330,3)
 var (numer, total) = arrayOf(x, x)
 for (i in 3..450 step 2) {
 numer = -numer * x * x
 total += numer / BigDecimal(i)
 }
 return total
}
answered Jun 24, 2018 at 19:58
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.