Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

델파이를 사용하여 실시간으로 Pi 자릿수를 보는 방법 (Pi 데이 기념)


Recommended Posts

Jim McKeeth"How to View Digits of Pi in Real-Time with Delphi for Pi Day 2024" 을 번역했습니다. (원문 작성: 2024년 3월, 최종 번역: 2024년 3월)

다음은 Embarcadero MVP이자 GDK 소프트웨어 미국 이사인 Jim McKeeth가 게시한 글이다. π 데이는 2024년에도 어김없이 돌아왔다 (옮긴이: 3월 14일은 π데이로 기념하기도 하고 아인슈타인 생일로도 기억하는데 이런 관점들이 유독 우리나라에서는 화이트 데이에 가려진 현실이 한편 안타깝기도 합니다). 나는 델파이 방식을 축하하기 위해, Rudy의 Big Numbers 라이브러리를 사용하여 만들었던 이전 샘플을 다시 열어서, π 숫자가 생성되는 동안 실시간으로 볼 수 있는 기능을 추가했다. 이전에는 어떤 자리수를 지정하든 그 만큼 생성해냈다. 하지만, 그 결과는 작업이 모두 완료된 후에 한꺼번에 표시되었었다.

차례


Rudy의 Big Numbers 라이브러리란?

이 라이브러리는 작고한 Rudy Velthuis가 원작자이다. 이 라이브러리는 델파이가 Big Integer, Big Decimal, and Big Rational 숫자를 지원할 수 있도록 추가한다. 얼마나 큰 수를? 글쎄, 여러분이 얼마나 큰 메모리를 가지고 있는냐에 달려있다. 최대값에 대한 한계는 실제로 없다.

이 라이브러리는 매우 사용하기 쉽고, 성능은 놀라울 정도로 좋다. 매우 다양한 샘플, 데모, 유닛 테스트들이 있다.  BigRational 타입은 실험 중이라고 표시되어 있으며, BigInteger들은 BigDecimal들보다 성능이 더 좋은 경향이 있다.

Pi를 델파이로 생성하는 방법은?

작년에 나는 이 샘플을 작성하여 델파이를 가지고 Pi를 계산했었다. 그 샘플은 Chudnovsky 알고리즘과 Bailey Borwein Plouffe (BBP)  알고리즘 둘 다를 지원한다. BBP는 더 빠르며, 숫자를 순차적으로 생성해내는 일종의 꼭지이다. 그래서 나는 이 알고리즘에 콜백을 추가하는 것이 더 합리적이라고 생각했다. 이 콜백은 한번에 숫자 64 개를 반환한다. 하지만, 그 덩어리 크기는 여러분이 쉽게 바꿀 수 있다.

실시간으로, Pi의 십진수 값을 보자

Pi의 숫자 표시를 보면서 나는 묘하기도 하고 흥미롭다고 느꼈다. 현재는 콘솔 앱에서만 콜백 기능을 지원하고 있다. 하지만, 앞으로 파이어몽키 앱도 마찬가지로 업데이트할 예정이다.

Bailey-Borwein-Plouffe Pi Code를 델파이 안에서

업데이트된 코드 (이 콜백 함수가 담겨 있음)는 다음과 같다.

function BBPpi(Places: UInt64; CallBack: TChunkCallback = nil): TDigits;
// Bailey-Borwein-Plouffe
begin
  SetLength(Result, Places);
 
  var idx: Uint64 := 0;
  var q := BigInteger.One;
  var r := BigInteger.Zero;
  var t := BigInteger.One;
  var k := BigInteger.One;
  var n := BigInteger.Create(3);
  var l := BigInteger.Create(3);
 
  var buffer: TDigits;
  SetLength(buffer, CallbackChunkSize);
  var bufferIdx: Integer := 0;
 
  while true do
  begin
    if 4*q+r-t < n*t then
    begin
      result[idx] := n.AsInt64; // 딱 1 바이트(byte)임
      inc(idx);
 
      if Assigned(Callback) then
      begin
        buffer[bufferIdx] := n.AsInt64;
        inc(bufferIdx);
        // 버퍼가 가득 찼는지 확인한다. 그렇다면, 콜백을 호출하고 bufferIdx를 리셋한다
        if bufferIdx = CallbackChunkSize then
        begin
          Callback(buffer); // 버퍼를 사용해 콜백한다
          bufferIdx := 0; // 버퍼 인덱스를 리셋한다
        end;
      end;
 
      if idx >= places then break;
      var newR := 10 * (r - n * t);
      n := (10 * (3 * q + r)) div t - 10 * n;
      q := q * 10;
      r := newR;
    end
    else
    begin
      var newR := (2 * q + r) * l;
      var newN := (q * (7 * k)+2+(r * l)) div (t * l);
      q := q * k;
      t := t * l;
      l := l + 2;
      k := k + 1;
      n := newN;
      r := newR;
    end;
  end;
 
  // 남아 있는 버퍼를 다루기
  if (bufferIdx > 0) and Assigned(CallBack) then
  begin
    SetLength(buffer, bufferIdx); // 버퍼의 크기를 실제로 사용되는 크기에 맞춘다. 콜백 전에 수행함.
    CallBack(buffer);
  end;
end;

 여기 이 아래에 있는 예시는 위 코드를 호출한다. 그리고 나서 그 결과 숫자들을 한번에 하나씩 콘솔에 출력한다.

var firstChunk: Boolean = True;
procedure WritelnCallBack(Chunk: TDigits);
begin
  var digits: String;
  if firstChunk then
  begin
    digits := DigitsToString(Chunk).Insert(1,'.');
    firstChunk := False;
  end
  else
    digits := DigitsToString(Chunk);
 
  // 시연을 하기 위해서는 출력 속도를 늦춰라
  for var i := low(digits) to High(digits) do
  begin
    Write(digits[i]);
    sleep(100);
  end;
end;
 
const Places = 10000;
begin
  BBPpi(Places, WritelnCallBack);
  Writeln;
end.

현재, 위 코드는 익명 메서드 참조를 하나 사용하고 있다. 이것이 오버헤드가 조금 생긴다는 점을 나도 알고 있다 하지만, 그것으로 인해 얼마나 차이가 생기는지를 비교하지는 않았으며 그 콜백 타입을 변경할 필요가 있는지에 대해서도 크게 생각하지 않는다. 속도를 약간 늦춰야 한다고 생각했는데, 이 프로그램의 목적은 숫자를 보는 것이기 때문이다.

또한 유닛 테스트를 하나 추가했다. 콜백으로부터 나오는 출력이 함수 호출의 결과와 일치하는지 확인하기 위해서이다.

Delphi/Pascal
procedure BBPpiTest.CompareCallbackToResult;
begin
  var CallBackString := '';
  var CallBackStringBuilder: TChunkCallBack := procedure(Chunk: TDigits)
  begin
    CallBackString := CallBackString + DigitsToString(Chunk);
  end;
 
  var calcPi := DigitsToString(BBPpi(100, CallBackStringBuilder));
  Assert.AreEqual(calcPi, CallBackString);
end;

이 멋진 Vaporwave Athena Pi Day 배경 이미지를 어디에서 얻을 수 있는가 ?

좋은 질문이다! 나는 이것은 4K까지 키웠다. 그리고 변형 버전들도 몇 가지있다...

spacer.png

이 예시들 중 몇 가지를 직접 해보고 싶은가?  RAD 스튜디오 최신 버전의 무료 평가판을 다운로드 할 수 있다.

(이 기고는 엠바카데로 MVP가 작성했음)

이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.