我是Scheme语言的新手。我想制作一个计算税收的程序。例如:
Price < 50 ---------------------------------------> Tax = %15
Price > 50 && Prize < 100 ------------------> Tax = %10
Price > 100 --------------------------------------> Tax = %5
有没有办法在不使用DrRacket&amp ;;中的if / switch / condition语句的情况下进行此计算。方案
答案 0 :(得分:3)
由于这是家庭作业,所以不愿回答,但是......
首先,我将使用cond
来编写此内容:
#lang racket
(require rackunit)
(define (tax-rate price)
(cond [(< price 50) 0.15]
[(< price 100) 0.10]
[else 0.05]))
(check-equal? (tax-rate 1) 0.15)
(check-equal? (tax-rate 50) 0.10)
(check-equal? (tax-rate 100) 0.05)
接下来让我们考虑一下cond
。它说,“如果价格<50,则税率为0.15 或,如果价格<100,则税率为0.10,或,如果...... 。等等 ....“
请注意句子中的“或”。确实听起来像cond
是一种(or ...)
表达式。第一个真正的东西“胜利”。
有了这个提示,也许你可以搞清楚吗?否则,扰流警报。
您可以使用cond
和or
重写and
:
(define (tax-rate2 price)
(or (and (< price 50) 0.15)
(and (< price 100) 0.10)
0.05))
(check-equal? (tax-rate2 1) 0.15)
(check-equal? (tax-rate2 50) 0.10)
(check-equal? (tax-rate2 100) 0.05)
一般情况下,可以将cond
重写为or
,提供除了最后一个以外的任何分支都不需要返回#f
。由于tax-rate
永远不需要返回#f
,因此可以在此处使用。
答案 1 :(得分:2)
假设您被允许使用min
:
(define (tax price)
(/ (* price (- 15 (* 5 (min 2 (quotient price 50)))))
100.0))
min
将结果减少到2,如果有必要,税收为(15-2 * 5)%= 5%。测试:
> (tax 30)
4.5
> (tax 70)
7.0
> (tax 120)
6.0
并与使用条件的算法进行比较:
(for ((n 2000))
(let ((tax1 (tax n))
(tax2 (/ (* n (cond
((< n 50) 15)
((< n 100) 10)
(else 5)))
100.0)))
(unless (= tax1 tax2)
(printf "~a: fun= ~a man= ~a \n" n tax1 tax2 ))))
与使用cond
的公式没有区别(至少对于从0到1999的价格值)。
答案 2 :(得分:1)
确实有一种方法可以完全不使用任何条件,甚至是使用min
等条件的预定义函数,但如果你是Scheme的新手,你就不会去喜欢它,它可能不是你想要的。诀窍是回到裸骨lambda演算,从中派生出来。
首先,将原语重新定义为true和false,作为返回第一个或第二个参数的函数:
(define TRUE (lambda(t f) t))
(define FALSE (lambda(t f) f))
其次,将数字零定义为仅包含FALSE
的列表(我们甚至可以避免使用列表基元,但是对于一个简单的例子,这将做),并定义两个函数来递增和递减数字:< / p>
(define zero (list FALSE))
(define (inc n) (cons TRUE n))
(define (dec n) (rest n))
定义一些数字:
(define one (inc zero))
(define two (inc one))
(define three (inc two))
因此,非zero
的任何(正数)数字的第一个元素为TRUE
,而FALSE
为zero
。您可以使用此信息来定义一个函数,该函数将数字和两个函数作为参数,如果数字为正,则应用第一个函数,否则应用第二个函数:
(define (if-positive n proc-true proc-false)
(((first n)
proc-true
proc-false)))
;; TESTS
(if-positive three (lambda() 'positive) (lambda() 'zero)) ; -> 'positive
(if-positive zero (lambda() 'positive) (lambda() 'zero)) ; -> 'zero
现在,我们可以创建一个函数,它接受两个数字和两个过程,从每个数字递归地减去1,如果第一个数字首先达到0,则应用第一个过程,但如果第二个数字达到0则首先应用第二个过程过程:
(define (if-greater n1 n2 proc-true proc-false)
(if-positive
n1
(lambda()(if-positive
n2
(lambda()(if-greater (dec n1) (dec n2) proc-true proc-false))
proc-true))
proc-false))
;; TESTS
(if-greater three two (lambda() 0.15) (lambda() 0.1)) ; -> 0.15
(if-greater one two (lambda() 0.1) (lambda() 0.05)) ; -> 0.05
现在你需要做的就是定义数字100和50,你很高兴。当然这是非常不切实际的,但这就是你不使用if
所得到的。 (请注意,通过使用基数2而不是基数1可以使其更加实用,但对于此示例,这是一个细节。)
更多信息here例如,但对新手来说可能有点苛刻。