From: Emre Sevinc
Subject: How to print decimal fraction values in English?
Date: 
Message-ID: <r0lmzdfsagq.fsf@emba-emre.bilgi.networks>
What can be the idiomatic way to print values such
as 

12.23
1.456
2.3
.
.
.

in the form:

twelve point twenty three
one point four hundred fifty six
two point three

I used something like that but of course this is not a general
solution at all:

(multiple-value-bind (int fraction) (round 123.123)
  (format t "~r point ~r" int (truncate (* 1000 fraction))))

As you see since I know the length I have multiplied the fraction by 1000
however because of truncate there is another error, should the input
be 123.129 I would get the last digit as "eight" (obviously).

So what is the best way to ask Common Lisp:

- take this number

- give me its integer part

- give me its fractional part after the point (without rounding, 
truncating, etc.)


Regards,

-- 
Emre Sevinc

eMBA Software Developer         Actively engaged in:
http://emba.bilgi.edu.tr        http://ileriseviye.org
http://www.bilgi.edu.tr         http://fazlamesai.net
Cognitive Science Student       http://cazci.com
http://www.cogsci.boun.edu.tr

From: Eric Hanchrow
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <874pznfisg.fsf@offby1.atm01.sea.blarg.net>
>>>>> "Emre" == Emre Sevinc <·····@bilgi.edu.tr> writes:

    Emre> What can be the idiomatic way to print values such as

    Emre> 12.23 1.456 2.3 .  .  .

    Emre> in the form:

    Emre> twelve point twenty three
    Emre> one point four hundred fifty six

For what it's worth, I wouldn't call those idiomatic -- I would
instead pronounce those numbers as "twelve point two three" and "one
point four five six".

-- 
I think the future of the Republic may depend on young
audiences seeing more movies like "Whale Rider" and fewer
movies like "Scooby-Doo 2," but then that's just me.
        -- Roger Ebert
From: Ed Symanzik
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <e4i75q$1fj$1@news.msu.edu>
Eric Hanchrow wrote:
>>>>>> "Emre" == Emre Sevinc <·····@bilgi.edu.tr> writes:
> 
>     Emre> What can be the idiomatic way to print values such as
> 
>     Emre> 12.23 1.456 2.3 .  .  .
> 
>     Emre> in the form:
> 
>     Emre> twelve point twenty three
>     Emre> one point four hundred fifty six
> 
> For what it's worth, I wouldn't call those idiomatic -- I would
> instead pronounce those numbers as "twelve point two three" and "one
> point four five six".
> 

You might also say "twelve and twenty-three hundredths".
From: Pascal Bourguignon
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <87hd3nutjr.fsf@thalassa.informatimago.com>
Eric Hanchrow <······@blarg.net> writes:

>>>>>> "Emre" == Emre Sevinc <·····@bilgi.edu.tr> writes:
>
>     Emre> What can be the idiomatic way to print values such as
>
>     Emre> 12.23 1.456 2.3 .  .  .
>
>     Emre> in the form:
>
>     Emre> twelve point twenty three
>     Emre> one point four hundred fifty six
>
> For what it's worth, I wouldn't call those idiomatic -- I would
> instead pronounce those numbers as "twelve point two three" and "one
> point four five six".

More interesting examples would be:

1.01
1.0012
1.0000123

-- 
__Pascal Bourguignon__                     http://www.informatimago.com/

"You question the worthiness of my code? I should kill you where you
stand!"
From: Barry Margolin
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <barmar-5F4A1B.22291218052006@comcast.dca.giganews.com>
In article <··············@thalassa.informatimago.com>,
 Pascal Bourguignon <···@informatimago.com> wrote:

> Eric Hanchrow <······@blarg.net> writes:
> 
> >>>>>> "Emre" == Emre Sevinc <·····@bilgi.edu.tr> writes:
> >
> >     Emre> What can be the idiomatic way to print values such as
> >
> >     Emre> 12.23 1.456 2.3 .  .  .
> >
> >     Emre> in the form:
> >
> >     Emre> twelve point twenty three
> >     Emre> one point four hundred fifty six
> >
> > For what it's worth, I wouldn't call those idiomatic -- I would
> > instead pronounce those numbers as "twelve point two three" and "one
> > point four five six".
> 
> More interesting examples would be:
> 
> 1.01
> 1.0012
> 1.0000123

Especially since American speakers almost never pronounce the zeroes 
after the decimal point as "zero", but as "oh", e.g. "one point oh one" 
and "one point oh oh one two".  I'm not sure what British English 
speakers say -- I wouldn't be surprised if they say "zed".

So whatever you do would have to special-case the digit 0.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Tayssir John Gabbour
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <1147969757.659954.237360@j55g2000cwa.googlegroups.com>
Here's a quick hack... is something like this what you're looking for?

(defun print-float-english (float
                             &key (stream *standard-output*)
                             (digits-after-decimal 3))
  (destructuring-bind (before-decimal after-decimal)
      (split-sequence:split-sequence #\. (number->string float))
    (format stream "~R point ~R"
            (parse-integer before-decimal)
            (parse-integer (if digits-after-decimal
                               (subseq after-decimal
                                       0
                                       (min digits-after-decimal
                                            (length after-decimal)))
                               after-decimal)))))

(defun number->string (number)
  (with-output-to-string (s)
    (prin1 number s)))


CL-USER> (print-number-english 10.3929)
ten point three hundred ninety-two


Tayssir
From: Tayssir John Gabbour
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <1147976221.006617.120600@j55g2000cwa.googlegroups.com>
Tayssir John Gabbour wrote:
> Here's a quick hack... is something like this what you're looking for?

Let me retract that even though pointed out it's a quick hack, as my
head is too currently frazzled to sensibly post. (Weird day.)

Tayssir
From: Thomas A. Russ
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <ymilksznt6y.fsf@sevak.isi.edu>
Emre Sevinc <·····@bilgi.edu.tr> writes:

> What can be the idiomatic way to print values such
> as 
> 
> 12.23
> 1.456
> 2.3
> .
> .
> .
> 
> in the form:
> 
> twelve point twenty three
> one point four hundred fifty six
> two point three
> 
> I used something like that but of course this is not a general
> solution at all:
> 
> (multiple-value-bind (int fraction) (round 123.123)
>   (format t "~r point ~r" int (truncate (* 1000 fraction))))

Well, for starters, I would exchange the use of ROUND and TRUNCATE.  You
want to call TRUNCATE to get the integer and fraction parts, and then
round the results of your multiplication.

> As you see since I know the length I have multiplied the fraction by 1000
> however because of truncate there is another error, should the input
> be 123.129 I would get the last digit as "eight" (obviously).
> 
> So what is the best way to ask Common Lisp:
> 
> - take this number
> 
> - give me its integer part
> 
> - give me its fractional part after the point (without rounding, 
> truncating, etc.)

You want to use TRUNCATE.
You will, of course, run into floating point representation issues.

I suppose you could always work directly off of the string
represenation.

Assuming you have the split-sequence function:

(defun hack (number)
   ;; Allow junk in fraction part to handle things like "d0"
   ;; note that it will fail for exponents that are too large.
   (let* ((number-string (princ-to-string number))
          (.pos (position #\. number-string)))
      (if .pos
          (format nil "~r point ~r" 
                 (parse-integer (subseq number-string 0 .pos))
                 (parse-integer (subseq number-string (1+ .pos))
                                :junk-allowed t))
          (format nil "~r" number-string))))



(hack 123.129)
"one hundred twenty-three point one hundred twenty-nine"

(hack 123.4)
"one hundred twenty-three point four"

(hack pi)
"three point one hundred forty-one trillion five hundred ninety-two billion six hundred fifty-three million five hundred eighty-nine thousand seven hundred ninety-three"




--
Thomas A. Russ,  USC/Information Sciences Institute
From: Emre Sevinc
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <873bf79cpb.fsf@ileriseviye.org>
> You want to use TRUNCATE.
> You will, of course, run into floating point representation issues.
> I suppose you could always work directly off of the string
> represenation.

That was also disturbing me and I started to think of string
manipulation as you have already provided. 


> Assuming you have the split-sequence function:

Do I need split-sequence function? I didn't see you use it below:
 
> (defun hack (number)
>    ;; Allow junk in fraction part to handle things like "d0"
>    ;; note that it will fail for exponents that are too large.
>    (let* ((number-string (princ-to-string number))
>           (.pos (position #\. number-string)))
>       (if .pos
>           (format nil "~r point ~r" 
>                  (parse-integer (subseq number-string 0 .pos))
>                  (parse-integer (subseq number-string (1+ .pos))
>                                 :junk-allowed t))
>           (format nil "~r" number-string))))
> 

Yes, that's what I was looking for.

 
> (hack 123.129)
> "one hundred twenty-three point one hundred twenty-nine"
> 
> (hack 123.4)
> "one hundred twenty-three point four"
> 
> (hack pi)
> "three point one hundred forty-one trillion five hundred ninety-two 
> billion six hundred fifty-three million five hundred eighty-nine 
> thousand seven hundred ninety-three"

But I see that:

(princ-to-string 12345.34534345d0)
"12345.34534345d0"

(princ-to-string 12345.34534345)
"12345.346" 

I think that is the problem you mentioned for large exponents.

Thank you very much for a possible and quick solution. 


-- 
Emre Sevinc

eMBA Software Developer         Actively engaged in:
http:www.bilgi.edu.tr           http://ileriseviye.org
http://www.bilgi.edu.tr         http://fazlamesai.net
Cognitive Science Student       http://cazci.com
http://www.cogsci.boun.edu.tr
From: Thomas A. Russ
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <ymibqtunfz0.fsf@sevak.isi.edu>
Emre Sevinc <·····@bilgi.edu.tr> writes:
> > Assuming you have the split-sequence function:
> 
> Do I need split-sequence function? I didn't see you use it below:

Oops.  No, you don't need it.  I figured it was easy enough to code
directly so I changed my mind about using that function.  Tayssir's
solution used split-sequence, though.

> > (defun hack (number)
> >    ;; Allow junk in fraction part to handle things like "d0"
> >    ;; note that it will fail for exponents that are too large.
> >    (let* ((number-string (princ-to-string number))
> >           (.pos (position #\. number-string)))
> >       (if .pos
> >           (format nil "~r point ~r" 
> >                  (parse-integer (subseq number-string 0 .pos))
> >                  (parse-integer (subseq number-string (1+ .pos))
> >                                 :junk-allowed t))
> >           (format nil "~r" number-string))))
> > 
> 
> Yes, that's what I was looking for.

> But I see that:
> 
> (princ-to-string 12345.34534345d0)
> "12345.34534345d0"
> 
> (princ-to-string 12345.34534345)
> "12345.346" 
> 
> I think that is the problem you mentioned for large exponents.

No.  The issue with this is just the difference between double float and
single float.  The problem I was referring to was something more like

(princ-to-string 1.234d20)
"1.234d+20"

which would fail, since the exponent information is discarded by the
hack.

I suppose one could get around that (at least for positive exponents) by
using (format nil "~G" number) instead of princ-to-string.  There would
also need to be minor changes to the code to handle a single trailing
decimal point (with no fractional digits after it).  I don't have a
solution for negative exponents.

-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Kaz Kylheku
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <1148099520.772539.26800@g10g2000cwb.googlegroups.com>
Thomas A. Russ wrote:

> (hack pi)
> "three point one hundred forty-one trillion five hundred ninety-two billion six hundred fifty-three million five hundred eighty-nine thousand seven hundred ninety-three"

I think a better approach would be to take the decimal portion and take
it as a sequence of digits. Decompose the digits into groups of three
and call these out as if they were separate numbers.

A few special cases could be recognized.   For instance if there are
four digits after the decimal point, they could be broken into two and
two rather than three and one:  0.1234 would be "zero point twelve
thirty-four", and not "zero point one hundred twenty-three, four". But
0.12345 would be "zero point hundred twenty-three, forty-five".

Now within each group of three digits, the cases 010 through 099 would
be handled specially as "zero ten" through "zero ninety-nine".
Similarly 001 through 009 would be handled as "zero zero one" or
"double zero one" or "double oh one" thorugh "double zero nine" or
similar, the 007 case being noteworthy (double oh seven!). And 000
would be rendered as triple zero, triple oh, zero zero zero, or such.

By these means we could "decimate" just about any finite fraction.
From: Ari Johnson
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <m2zmhe1wii.fsf@hermes.theari.com>
Emre Sevinc <·····@bilgi.edu.tr> writes:

> What can be the idiomatic way to print values such
> as 
>
> 12.23
> 1.456
> 2.3
> .
> .
> .
>
> in the form:
>
> twelve point twenty three
> one point four hundred fifty six
> two point three

Why "point" instead of the following?

twelve and twenty-three hundredths
one and four hundred fifty-six thousands
two and three tenths

I think that the algorithm would be, roughly:

if length of decimal part = 0
elseif length of decimal part = 1
  print decimal part, "tenths"
elseif length of decimal part = 2
  print decimal part, "hundredths"
else
  print first three digits of decimal part, "thousandths"
  recurse on rest of decimal part into ten-thousands,
      hundred-thousandths, and millionths; etc.
From: Thomas A. Russ
Subject: Re: How to print decimal fraction values in English?
Date: 
Message-ID: <ymi7j4infky.fsf@sevak.isi.edu>
Ari Johnson <················@gmail.com> writes:

> I think that the algorithm would be, roughly:
> 
> if length of decimal part = 0
> elseif length of decimal part = 1
>   print decimal part, "tenths"
> elseif length of decimal part = 2
>   print decimal part, "hundredths"
> else
>   print first three digits of decimal part, "thousandths"
>   recurse on rest of decimal part into ten-thousands,
>       hundred-thousandths, and millionths; etc.

Simplified, with string input:

(defun hack-fraction (fraction-string)
  (format nil "~R ····@2*~P" 
          (parse-integer fraction-string)
          (expt 10 (length fraction-string))))


(hack-fraction "23")
"twenty-three one hundredths"

(hack-fraction "001")
"one one thousandth"

(hack-fraction "002")
"two one thousandths"

(hack-fraction "0012")
"twelve ten thousandths"


-- 
Thomas A. Russ,  USC/Information Sciences Institute