RAD 3월 15일에 포스트됨 공유하기 3월 15일에 포스트됨 원문제목: Calculating Pi in Delphi for Pi Day 2023 원문: https://blogs.embarcadero.com/calculating-pi-in-delphi-for-pi-day-2023/ 작성자: Jim McKeeth (2023.3) In the United States today, March 14th is π day (3rd month, 14th day, or 3/14). Traditions involve eating pie, the pastry, and calculating Pi, the irrational mathematical constant. 3월 14일은 '원주율의 날'이라는 사실, 미국의 경우 실제로 π 데이로 기념한다고 한다. 이 날에는 파이, 패스츄리를 먹거나 수학 상수인 Pi를 계산한다고 한다. 원의 둘레를 펴는 모습을 보여주는 애니메이션으로, π 비율을 보여준다. John Reid [CC BY-SA 3.0]가 위키피디아를 통해 편집 In Delphi, Pi is included as an intrinsic function. If you look in the System unit there are references, but no definition. It has a floating point value of 3.141592653589793238 (although you don’t usually see the last few digits). This is more accuracy than even NASA uses. But for theoretical mathematics and certain definitions of fun, we can do better. 델파이에는 파이가 내장 함수로 포함되어 있다. 시스템 단위를 보면 참조는 찾을 수 있지만, 명확한 정의는 없다. 부동 소수점 숫자로 3.141592653589793238라는 값을 제공한다 (하지만 마지막 일부 숫자는 잘 보지 못했을 것이다). 심지어 NASA에서 사용하는 것보다 훨씬 더 정확하다. 이론적인 수학 그리고 재미 부분에서는 더 뛰어날 수도 있다. As an irrational number, the decimal portion goes on forever without repeating. So when you calculate Pi you go through iterations improving your accuracy, or the number of digits precision. Google recently calculated 100 Trillion digits of Pi. It took 157 days, 23 hours, 31 minutes and 7.651 seconds on a 128 vCPUs with 864 GB RAM, 515 TB storage, and 82 PB of I/O. This was an opportunity to show off their cloud computing infrastructure. So the practical among us would just download the digits we need (as long as it is less than 100 trillion). Pi는 무리수로, 소수 부분은 반복없이 영원히 계속된다. 따라서 Pi를 계산할 때 다양한 반복 과정을 거쳐 정확도를 높이고 자릿수 정밀도를 향상시킬 수 있다. 구글은 최근 Pi를 100조 자릿수까지 계산해냈다. 이를 위해 157일 23시간 31분 7.651초가 소요되었으며, 864 GB RAM, 515 TB 저장소, 82 PB I/O를 갖춘 128 vCPU를 사용했다. 이 기회를 통해 구글의 클라우드 컴퓨팅 능력을 자랑한 것이다. 다만 우리 중 실용적인 사람이라면 필요한 자릿수까지만 받을 듯하다 (100조 미만인). When it comes to calculating Pi there are a number of different algorithms. Many of us may have memorized a few digits, or some other approximation. But what if we want to calculate more? I poked around the web and even consulted Wolfram Alpha and ChatGPT. Here are a few examples I put together for you. Pi를 계산할 수 있는 다양한 알고리즘들이 있다. 우리 중 대다수가 일부 소수점 수나 근사치까지는 외우고 있을 것이다. 하지만 더 많은 것을 계산하고 싶다면? 나의 경우엔 웹을 뒤지거나 Wolfram Alpha와 ChatGPT까지도 살펴보았다. 그리고 여러분을 위해 정리한 몇 가지 예제들을 공유한다. 목차 라이프니츠의 파이 공식 닐칸타 활용하기 베일리-보르웨인-플루프 파이 공식 루디의 Big Decimals 활용하기 결론 라이프니츠의 파이 공식 Named after Gottfried Leibniz, this formula comes from approximately the 14th century. I found a few examples in Delphi, and massaged them into the following implementation: 고프트리트 라이프니츠의 이름을 딴 이 공식은 대략 14세기에 만들어졌다. 델파이에서 몇 가지 예제를 찾아, 다음과 같이 구현해보았다: function LeibnizPi(const Iterations: NativeUInt): Extended; begin Result := 0; var k: Extended := 1; for var I := 0 to Iterations do begin if odd(I) then Result := Result - 4 / k else Result := Result + 4 / k; k := k + 2; end; end; This ends up being rather slow and inaccurate. Running it for MaxInt iterations results in a value of 3.14159265312413, only accurate to 9 decimal places. 다소 속도가 느리고 부정확하기는 하다. 이 값을 MaxInt까지 반복 실행하면 소수점 이하 9자리까지만 정확한 3.14159265312413라는 결과값이 계산된다. 닐칸타 활용하기 My notes say this is Nilkantha, but now I’m not sure. It was a bit more accurate than Leibniz, thus saving some time. 노트에 닐칸타(Bilkantha)라고 적어놓았는데, 확실하지는 않다. 다만 이 결과물이 라이프니츠보다 조금 더 정확해 시간을 절약할 수 있었다. function NilkanthaPi(const Iterations: NativeUInt): Extended; begin Result := 3; var n: Extended := 2; var sign := 1; for var I := 0 to Iterations do begin Result := Result + sign * (4 / (n * (n + 1) * (n + 2))); sign := sign * -1; n := n + 2; end; end; 1000 iterations is accurate to 9 decimal places and 11,000 iterations is accurate to 12 places. 1000개의 항을 계산하면 소수점 이하 9자리까지, 11,000개의 항을 계산하면 소수점 이하 12자리까지는 정확하다. If someone recognizes this as a different algorithm, please let me know. 이 알고리즘을 다른 알고리즘으로 인식한다면 알려주기 바란다. 베일리-보르웨인-플루프 파이 공식 This formula was discovered in 1995 by Simon Plouffe. The BBP formula gives rise to a spigot algorithm for computing the nth base-16 (hexadecimal) digit of π (and therefore also the 4nth binary digit of π). When I started trying to convert it to Delphi code I decided to give ChatGPT a shot, and it got me really close to working code. A little clean up gave me the following: 이 공식은 1995년 사이먼 플러프가 발견했다. BBP 공식은 π의 n번째 16진수를 계산할 스피곳(spigot) 알고리즘을 생성한다 (π의 4n번째 자리까지도 동일하다). 델파이 코드로 변환해보려고 하다가, 이 기회를 ChatGPT에서 줘보기로 했다. 그리고 정말 작동하는 코드에 가깝도록 만들어냈다. 살짝 다듬어서 다음과 같은 코드를 완성할 수 있었다: function BaileyBorweinPlouffePi(const Digits: NativeUInt): Extended; begin Result := 0; for var I := 0 to Digits do begin Result := Result + 1 / power(16, I) * ((4 / (8 * I + 1)) - (2 / (8 * I + 4)) - (1 / (8 * I + 5)) - (1 / (8 * I + 6))); end; end; This one is very fast, and indicating 10 digits is more than enough. 속도도 굉장히 빨랐고, 10자리 숫자를 표시하는 것도 충분했다. 루디의 Big Decimals 활용하기 What if we want more than 10 digits of accuracy? Well, the late great Rudy Velthuis created a BigNumbers library which is available on GitHub. It includes BigIntegers, BigDecimals, and BigRationals, along with a number of other useful libraries. I converted the BBP algorithm to use BigDecimals and ended up with the following: 10자리 이상의 정확도가 필요하다면? 루디 벨트하위스(Rudy Velthuis)의 BigNumbers 라이브러리를 활용하면 된다. 현재 깃허브(GitHub)에서 받을 수 있다. 여기에 BigIntegers, BigDecimals, BigRationals와 더불어 여러 유용한 라이브러리들이 포함되어 있다. 나는 BigDecimals 활용을 위해 BBP 알고리즘을 변환했고, 다음과 같은 결과를 얻을 수 있었다: function BigBaileyBorweinPlouffePi(const Digits: NativeUInt): BigDecimal; begin const sixteen = BigDecimal.Create(16); Result := BigDecimal.Zero; Result.DefaultPrecision := Digits; for var I := 0 to Digits do begin var term1 := BigDecimal.Create((4 / (8 * I + 1)) - (2 / (8 * I + 4)) - (1 / (8 * I + 5)) - (1 / (8 * I + 6))); var term2 := BigDecimal.Divide(1, sixteen.IntPower(I), Result.DefaultPrecision); Result := Result + BigDecimal.Multiply(term1, term2); end; end; It is still very fast, and outputs very long numbers, but unfortunately I was still only able to get about 20 digits accurately. 속도는 여전히 매우 빠르고, 출력되는 숫자도 매우 길다. 하지만 약 20자리까지만 결과가 정확했다. 결론 The pi built into Delphi is more than enough for most uses, but it is nice to look at the options for generating pi from scratch with Delphi. I’ve posted all my code on GitHub in a Gist, and will update it if I make any improvements based on more testing or feedback. Also, if you find yourself needing bigger Integers or Decimals, check out Rudy’s library. 델파이에 내장되어 있는 pi는 대부분이 용도에 충분하지만, 델파이를 사용해 pi를 생성하는 코드를 첫 단계부터 만들어 볼 수 있는 코드를 Gist에 있는 깃허브에 올려두었다. 테스트를 더 해보고 피드백을 받아 이를 기반으로 코드를 업데이트할 예정이다. 더 큰 정수나 소수가 필요하다면 루디의 라이브러리를 참고하기 바란다. [전체 코드 보기] 인용하기 이 댓글 링크 다른 사이트에 공유하기 더 많은 공유 선택 사항
Recommended Posts
이 토의에 참여하세요
지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.