如果我尝试在 Chicken Scheme(带有数字扩展名)和 Clisp 中计算表达式 (expt 123456 123456)
,它会花费相当长的时间(在 Clisp 中更多)。
所以我认为计算表达式 (/(expt 123456 123456) (expt 123456 123456))
至少需要两倍的时间,因为解释器必须计算两倍的幂函数,然后必须计算一个部门。
但是,令人惊讶的是,两个口译员的答案几乎是瞬间就出来了。到底是怎么回事?怎么可能?确切地说,这个表达式是如何求值的?
最佳答案
在 Common Lisp 中你有 time
宏:
(time (progn (expt 123456 123456) 1))
; Real time: 0.578002 sec.
; Run time: 0.577577 sec.
; Space: 733816 Bytes
; GC: 1, GC time: 0.007143 sec.
; ==> 1
(time (progn (princ (expt 123456 123456)) 1))
; a whole lot of numbers ...6
; Real time: 59.980278 sec.
; Run time: 59.017193 sec.
; Space: 8490376 Bytes
; GC: 4, GC time: 0.033218 sec.
; ==> 1
它们之间的区别在于以人类可读的十进制方式生成数字并将其输出到慢速控制台。
第二个表达式的用时大约是第一个表达式的两倍:
(time (/ (expt 123456 123456) (expt 123456 123456)))
; Real time: 1.120879 sec.
; Run time: 1.11894 sec.
; Space: 1728656 Bytes
1
确实如此.. 打印第一个表达式的结果如何:
(let ((value (time (expt 123456 123456))))
(time (princ value))
1)
; Real time: 0.584907 sec. (pretty much the same time calculating the result)
; Run time: 0.584398 sec.
; Space: 733816 Bytes
; GC: 1, GC time: 0.020312 sec.
; lots of digits ...56
; Real time: 59.803486 sec. about the same time it took printing it last time
; Run time: 58.414997 sec.
; Space: 2514768 Bytes
; GC: 1, GC time: 0.002712 sec.
; ==> 1
我认为我不需要在 Scheme 中重复这一点。控制台很慢,CL 和 Scheme 中的算术很快,即使是大数字也是如此。
编辑
我实际上确实制作了一个脚本并将其重定向到一个文件,并且它花费了大约相同的时间。因此,大部分时间用于将 bignum 转换为人类可读的字符,而不是实际将其输出到控制台上。如果是控制台将其重定向到文件,将大大加快整个过程。
关于math - Lisp 中的算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31974240/