2007. június 30., szombat

Converting Numbers to words


Problem/Question/Abstract:

How to convert numbers like 2345697.347 to "two billion, three hundred and forty-five thousand, six hundred and ninety seven decimal three four seven."

Answer:

unit Inwordsu;

interface
uses SysUtils, Dialogs;

function InWords(const nNumber: Extended): string;

implementation

function InWords(const nNumber: Extended): string;
const
  aUnits: array[0..9] of string = ('', 'one ', 'two ', 'three ', 'four ', 'five ',
    'six ', 'seven ', 'eight ', 'nine ');
  //Local function to convert decimal portion
  function cDecimal(const cDecDitxt: string): string;
  var
    len, x, n: Integer;
    nNumber: string[17];
  begin
    result := '';
    nNumber := cDecDitxt;
    //cut off Zeros to the right
    while copy(nNumber, length(nNumber), 1) = '0' do
      delete(nNumber, length(nNumber), 1);
    len := length(nNumber);
    //No need to convert if it is all zeros
    if len = 0 then
      exit;
    //Start conversion !
    for x := 1 to len do
    begin
      n := strToint(copy(nNumber, x, 1));
      if n = 0 then
        result := result + 'zero '
      else
        result := result + aUnits[n];
    end;
    if result <> '' then
      result := ' decimal ' + trim(result);
  end;

  //Local function to convert the whole number portion
  function Num2EngWords(const nNumber, nWordIndex: integer): string;
  const
    aLargeNumWords: array[0..5] of string = ('', 'thousand, ', 'million, ',
      'billion, ', 'trillion, ', 'quadrillion, ');
    aTens: array[0..8] of string = ('', 'twenty', 'thirty', 'forty', 'fifty', 'sixty',
      'seventy', 'eighty', 'ninety');
    aTwenties: array[10..19] of string = ('ten ', 'eleven ', 'twelve ', 'thirteen ',
      'fourteen ', 'fifteen ', 'sixteen ', 'seventeen ', 'eighteen ', 'nineteen ');
  var
    nQtnt, nNum, nMod: Integer;
  begin
    result := '';
    if nNumber < 1 then
      exit;
    nNum := nNumber;

    if nNumber > 99 then
    begin
      //Pick up hundreds and leave others
      nQtnt := nNum div 100;
      nNum := nNum mod 100;
      result := aUnits[nQtnt] + 'hundred and ';
    end;
    case nNum of
      1..9: result := result + aUnits[nNum]; {one to nine}
      10..19: result := result + aTwenties[nNum]; {ten to nineteen}
      20..99:
        begin
          nQtnt := nNum div 10;
          nMod := nNum mod 10;
          result := result + aTens[nQtnt - 1]; {digit at tenth place}
          if nMod <> 0 then
            result := result + '-' + aUnits[nMod] {digit at unit place}
          else
            result := result + ' ';
        end
    else
      if result <> '' then
        result := copy(result, 1, length(result) - 4);
    end;
    result := result + aLargeNumWords[nWordIndex]; {add thousand, million etc...}
  end;
var
  nNum, nIndex: Integer;
  cStr, cDec: string;
  lNegative: Boolean;
begin
  result := '';
  if (nNumber > 999999999999999999.0) then
  begin
    showmessage('Sorry this is too large ! larger than the budget of the whole world !!');
    exit;
  end;
  str(nNumber: 34: 15, cStr);
  lNegative := False;
  nIndex := pos('-', cStr); {having - sign is negative}
  if nIndex > 0 then
  begin
    lNegative := True;
    cStr := copy(cStr, nIndex + 1, length(cStr) - nIndex); {trim off minus sign}
  end;
  while cStr[1] = ' ' do {trim of spaces}
    delete(cStr, 1, 1);
  nIndex := pos('.', cStr); {decimal position}
  if nIndex = 0 then
    nIndex := length(cStr) + 1; {if no decimal it must be at the far right}
  cDec := copy(cStr, nIndex + 1, length(cStr) - nIndex); {digits after decimal point}
  cStr := copy(cStr, 1, nIndex - 1); {digits before decimal point}
  nIndex := 0; {index to point the words thousand, million etc.}
  nNum := length(cStr); {count of digits}
  while nNum > 0 do
  begin
    if nNum < 3 then
    begin
      result := Num2EngWords(strToInt(copy(cStr, 1, nNum)), nIndex) + result;
      cstr := ''; {less than 3 digits means finished}
    end
    else
    begin
      result := Num2EngWords(strToInt(copy(cStr, nNum - 2, 3)), nIndex) + result;
      cStr := copy(cStr, 1, nNum - 3); {cut off three rightmost digits}
    end;
    nNum := length(cStr); {remaining number of digits}
    inc(nIndex); {increase the large number's word index}
  end;
  result := trim(result) + cDecimal(cDec) + '.'; {finished, add a full stop}
  if lNegative then
    result := 'minus ' + result; {if the number is negative add "minus" at first}
end;

//Thanks Mr. KRISHNA SAPKOTA
//E-Mail: krishna_sapkota@hotmail.com
//for pointing out the misspelled function name in the calling example
//below !

//Calling examples:
{nNum:extended or nNum:Double}
//nNum:=24693456799398.6078;
{Corrected calling function name on Monday May 21, 2001}
//label1.caption:=InWords(nNum);
{nInt:Integer or nInt:longint}
//nInt:=23456
//label2.caption:=InWords(nint);
//label3.caption:=InWords(2345678965432.30045);
//label4.caption:=InWords(896867);

end.

Nincsenek megjegyzések:

Megjegyzés küldése