(SCHEME) Number -> 英文列表

(SCHEME) Number -> English List

好的。所以我想知道如何创建一个将随机数转换为其英文单词组成部分的函数。

如(1001 -> '(一千一)或0 -> '(零) and (number-name factorial 20 -> ’(2 quintillion 432 quadrillion 902 兆八十亿七千六百六百 四万))

我在 Whosebug 上与以前的用户合作,得到了一些东西,可以将一个长数字变成 3 个部分数字(1,341,100 是一百万,341,000 100 0 十 0 个)

 #lang r5rs
 (define (three-names n)
   (if (zero? n)
  "zero"
  (let loop ((n n)
             (units '((10 one) (10 ten) (10 hundred) (1000 thousand) (1000 million)  (1000 billion) (1000 trillion) (1000 quadrillion) (1000 quintillion)
                             (1000 sextillion) (1000 septillion) (1000 octillion) (1000 nonillion)
                             (1000 decillion) (1000 undecillion) (1000 duodecillion) (1000 tredecillion)
                             (1000 quatturodecillion) (1000 sexdillion) (1000 septendecillion) (1000 octodecillion)
                             (1000 novemdecillion) (1000 vigintillion)))
             (ARRAY '()))

    (if
     (or (zero? n) (null? units)) 
        ARRAY
        (let* ((unit (car units)) (div (car unit)) (english (cadr unit)))
          (let
              ((q (quotient n div)) (r (remainder n div)))
            (loop q
                  (cdr units)
                  (cons r (cons english ARRAY)))))))))    

我现在唯一理解的就是让它有 0-20 的值:

 (= x 0) zero
 (= x 1) one
 ...
 (> x 1000) thousand
 (> x 1000000) million

但是一方面,这些不会输出到列表中;另一方面,不知道还能做什么?

正如您可能知道的那样,您应该能够执行以下操作:

(number->english 2345678213) 
; ==> "two billion three hundred and fourtyfive million six \
;      hundred and seventyeight tousand two hundred and thirteen"

乍一看,有一个规律:

...
<english number text below 1000> million
<english number text below 1000> thousand
<english number text below 1000> 

因此..该过程可能类似于:

(define (number->english x)
  (if (zero? x)
      "zero"
      (iterate-thousands x thousands '()))

thousands 被定义为:'("" "thousand" "million" "billion" "trillion" ...)iterate-tousands 可能看起来像这样:

(define (iterate-thousands thousands x acc)
  (if (zero? x)
      (join acc " ")
      (iterate-thousands (cdr thousands)
                         (quotient x 1000)
                         (list* (below-1000 (remainder x 1000))
                                (car thousands) 
                                acc))))

其中 below-1000 returns 1000 以下的每个数字的正确字符串。它通常会根据命名约定划分工作。这对于 13 岁以下的人来说是特别的,直到 19 岁的青少年,复合 ty + ones 直到 99 并且可能对上面的递归采用 ones +“hundred”+ 对余数的递归,以便 234 变为 (string-append "two hundred and " (below-1000 34)). join 只需使用带有分隔符的 string-append 并正确处理空字符串。

正如 Sylwester 解释的那样,您需要能够

  1. 正确打印每个低于 1000(3 位)的数字的文本
  2. 将数字分成 3 位数字组,使用上面的代码打印它们并仅附加 "thousands" 就足够了

这是一个与 Racket 的 r5rs 语言兼容的示例实现:

(define (n2t n)
  (define 1to19     '(one two three four five six seven eight nine ten eleven twelve
                          thirteen fourteen fifteen sixteen seventeen eighteen nineteen))
  (define multof10  '(twenty thirty forty fifty sixty seventy eighty ninety))
  (define thousands '(thousand million billion trillion quadrillion quintillion sextillion septillion octillion nonillion decillion undecillion))
  (cond
    ((= n 0) '(zero))  ; zero is a special case since from now on all 0 will be suppressed
    ((< n 0) (cons 'minus (n2t (- n))))
    (else
     (let loop ((n n) (units thousands) (res '()))
       (cond
         ; --- below 1000
         ((= n 0)    res)
         ((< 0 n 20) (cons (list-ref 1to19    (- n 1)) res))
         ((< n 100)  (cons (list-ref multof10 (- (quotient n 10) 2))
                           (loop (remainder n 10) '() res)))
         ((< n 1000) (loop (quotient n 100)
                           '()
                           (cons 'hundred (loop (remainder n 100) '() res))))
         (else
          ; --- 1000 and above
          (let ((q   (quotient n 1000))
                (res (loop (remainder n 1000) thousands res)))
            (if (zero? q)
                res
                (loop q (cdr units) (cons (car units) res))))))))))

测试:

> (n2t 0)
'(zero)
> (n2t 1001)
'(one thousand one)
> (n2t 132219)
'(one hundred thirty two thousand two hundred nineteen)
> (n2t -132219)
'(minus one hundred thirty two thousand two hundred nineteen)
> (n2t 2345678213)
'(two billion three hundred forty five million six hundred seventy eight thousand two hundred thirteen)
> (n2t 2432902008176640000)
'(two quintillion four hundred thirty two quadrillion nine hundred two trillion eight billion one hundred seventy six million six hundred forty thousand)