230 likes | 421 Views
PRACTICAL COMMON LISP. Peter Seibel http://www.gigamonkeys.com/book/. CHAPTER 10 NUMBERS, CHARACTERS, AND STRINGS. REFACTORING. Common Lisp provides built-in support for most of the data types typically found in modern languages: numbers (integer, floating point, and complex),
E N D
PRACTICAL COMMON LISP Peter Seibel http://www.gigamonkeys.com/book/
REFACTORING • Common Lisp provides built-in support for most of the data types typically found in modern languages: • numbers (integer, floating point, and complex), • characters, • strings, • arrays (including multidimensional arrays), • lists, • hash tables, • input and output streams, and • an abstraction for portably representing filenames. • This chapter will cover the built-in “scalar” data types: numbers, characters, and strings.
NUMBERS • Lisp was originally designed by a mathematician (數學家) as a tool for studying mathematical functions. • Its numbers behave more like truemathematical numbers than the approximations of numbers. • For instance • Integers in Common Lisp can be almost arbitrarilylarge rather than being limited by the size of a machine word. • And dividing two integersresults in an exact ratio, not a truncated value. • Common Lisp also offers several types of floating-point numbers. • Common Lisp supports complex numbers—the numbers that result from doingthings such as taking square roots and logarithms of negative numbers.
NUMERIC LITERALS • For a given number of a given type, there can be manydifferent textual representations, all of which will be translated to the same object representationby the Lisp reader. • For instance, you can write the integer 10 as 10, 20/2, #xA, or any of a number of other ways, but the reader will translate all these to the same object. CL-USER> 10 10 CL-USER> 20/2 10 CL-USER> #xa ;十六進位表示法 #xa - #xf 10 CL-USER> #b1010 ;二進位表示法 10 CL-USER> #o12 ;八進位表示法 10
NUMERIC LITERALS • It’s also possible to write rationals(有理數) in bases other than 10. • If preceded by #B or #b, a rationalliteral is read as a binary number with 0 and 1 as the only legal digits. • An #O or #o indicates anoctal number (legal digits 0–7), and #X or #x indicates hexadecimal (legal digits 0–F or 0–f). • Youcan write rationals in other bases from 2 to 36 with #nR where n is the base (always written indecimal). • Additional “digits” beyond 9 are taken from the letters A–Z or a–z. #b10101 → 21 #b1010/1011 → 10/11 #o777 → 511 #xDADA → 56026 #36rABCDEFGHIJKLMNOPQRSTUVWXYZ → 8337503854730415241050377135811259267835
NUMERIC LITERALS • You can also write floating-point numbers in a variety of ways. • Common Lisp defines four subtypes of floating-point number: short, single, double, and long. • The exponent markers s, f, d, l (and theiruppercase equivalents) indicate short,single, double, and long floats, respectively. • The letter does double duty: it marks the beginning of the exponent and indicates what floatingpointrepresentation should be used for the number. • The letter eindicates that the default representation (initially single-float) should be used. 1.0 → 1.0 1e0 → 1.0 1d0 → 1.0d0 123.0 → 123.0 123e0 → 123.0 0.123 → 0.123 .123 → 0.123 123e-3 → 0.123 123E-3 → 0.123 0.123e20 → 1.23e19 123d23 → 1.23d25
NUMERIC LITERALS • Complex numbers are written in their own syntax, • #C or #c followed by alist of two real numbers representing the real(實數) and imaginary(虛數) part of the complex number. • No complex numbers have a rational real component and a zero imaginary part, they’re represented by the appropriaterational value. #c(2 1) → #c(2 1) #c(2/3 3/4) → #c(2/3 3/4) #c(2 1.0) → #c(2.0 1.0) #c(2.0 1.0d0) → #c(2.0d0 1.0d0) #c(1/2 1.0) → #c(0.5 1.0) #c(3 0) → 3 #c(3.0 0.0) → #c(3.0 0.0) #c(1/2 0) → 1/2 #c(-6/3 0) → -2
BASIC MATH • The basic arithmetic operations—addition, subtraction, multiplication, and division—aresupported for all the different kinds of Lisp numbers with the functions +, -, *, and /. (+ 1 2) →3 (+ 1 2 3) → 6 (+ 10.0 3.0) → 13.0 (+ #c(1 2) #c(3 4)) → #c(4 6) (- 5 4) → 1 (- 2) → -2 (- 10 3 5) → 2 (* 2 3) → 6 (* 2 3 4) → 24 (/ 10 5) →2 (/ 10 5 2) → 1 (/ 4) → 1/4 • If any of the arguments are complex, anyreal arguments are converted to the complex equivalents. (+ 1 2.0) → 3.0 (/ 2 3.0) → 0.6666667 (+ #c(1 2) 3) → #c(4 2) (+ #c(1 2) 3/2) → #c(5/2 2) (+ #c(1 1) #c(2 -1)) → 3
BASIC MATH • Because / doesn’t truncate, Common Lisp provides four flavors of truncating and roundingfor converting a real number to an integer: • FLOOR truncates towardnegative infinity, returning the largest integer less than or equal to the argument. • CEILINGtruncates toward positive infinity, returning the smallest integer greater than or equal to theargument. • TRUNCATE truncates toward zero, making it equivalent to FLOOR for positive argumentsand to CEILING for negative arguments. • And ROUND rounds to the nearest integer. • If the argumentis exactly halfway between two integers, it rounds to the nearest even integer.
BASIC MATH • Two related functions are MOD and REM, which return the modulus and remainder of atruncating division on real numbers. • These two functions are related to the FLOOR andTRUNCATE functions as follows: (+ (* (floor (/ x y)) y) (mod x y)) ≡ x (+ (* (truncate (/ x y)) y) (rem x y)) ≡ x
BASIC MATH • The functions 1+ and 1- provide a shorthand way to express adding and subtracting onefrom a number. • Note that these are different from the macros INCF and DECF. • 1+ and 1- are justfunctions that return a new value, but INCF and DECF modify a place. • The following equivalencesshow the relation between INCF/DECF, 1+/1-, and +/-: (incf x) ≡ (setf x (1+ x)) ≡ (setf x (+ x 1)) (decf x) ≡ (setf x (1- x)) ≡ (setf x (- x 1)) (incf x 10) ≡ (setf x (+ x 10)) (decf x 10) ≡ (setf x (- x 10))
NUMERIC COMPARISONS • The function = is the numeric equality predicate. • It compares numbers by mathematical value,ignoring differences in type. (= 1 1) → T (= 10 20/2) → T (= 1 1.0 #c(1.0 0.0) #c(1 0)) → T • The /= function returns true only if all its arguments are different values. (/= 1 1) → NIL (/= 1 2) → T (/= 1 2 3) → T (/= 1 2 3 1) → NIL (/= 1 2 3 1.0) → NIL
NUMERIC COMPARISONS • The functions <, >, <=, and >= order rationals and floating-pointnumbers. (< 2 3) → T (> 2 3) → NIL (> 3 2) → T (< 2 3 4) → T (< 2 3 3) → NIL (<= 2 3 3) → T (<= 2 3 3 4) → T (<= 2 3 4 3) → NIL • To pick out the smallest or largest of several numbers, we can use the function MIN or MAX, which takes any number of real number arguments and returns the minimum or maximum value. (max 10 11) → 11 (min -12 -10) → -12 (max -1 2 -3) → 2
NUMERIC COMPARISONS • Some other functions are ZEROP, MINUSP, and PLUSP, which test whether a single real number is equal to, less than, or greater than zero. • Two other predicates, EVENP and ODDP, test whether a single integer argument is even or odd. • The P suffix on the names of these functions is a standard naming convention for predicate functions, functions that test some condition and return a boolean. • Lisp also supports • logarithms: LOG; • exponentiation: EXP and EXPT; • the basic trigonometric functions: SIN, COS, and TAN; • their inverses: ASIN, ACOS, and ATAN; • hyperbolic functions: SINH, COSH, and TANH; and • their inverses: ASINH, ACOSH, and ATANH. • It also provides functions to get at the individual bits of an integer and to extract the parts of a ratio or a complex number.
EXERCISE • Write a function NUMCOM which can read two positive number, and calculate all the prime numbers between their sum and product values. For example: >(numcom) Please input two positive numbers: 2 7 The prime numbers between 9 and 14 are 11 and 13. Do you want to try again? Y Please input two positive numbers: 2 -7 -7 is not a positive number. Do you want to try again? Y Please input two positive numbers: a 7 a is not a number. Do you want to try again? N NIL
CHARACTERS • Common Lisp characters are a distinct type of object from numbers. • The read syntax for characters objects is simple: #\ followed by the desired character. • Thus, #\x is the character x. • Any character can be used after the #\, including otherwise special characters such as ", (, and whitespace. • We can write #\Space instead of #\ , though the latter is technically legal. • Other semistandard names are Tab, Page, Rubout, Linefeed(換行), Return, and Backspace.
CHARACTER COMPARISONS • The main thing you can do with characters, other than putting them into strings, is to compare them with other characters. • For example: Break 10 [11]> (char= #\e #\E) NIL Break 10 [11]> (char-equal #\e #\E) T
STRINGS • Literal strings are written enclosed in double quotes. • We can include any character supported by the character set in a literal string except double quote (") and backslash (\). • For examples: CL-USER> "foo\"bar" "foo\"bar" • CL-USER> (format t "foo\"bar") • foo"bar • NIL
STRING COMPARISONS • We can compare strings using a set of functions that follow the same naming convention as the character comparison functions except with STRING as the prefix rather than CHAR. • For example: Break 10 [11]> (string= "THIS" "this") NIL Break 10 [11]> (string-equal "THIS" "this") T
STRING COMPARISONS • The string comparators can compare two substrings. • The arguments—:start1, :end1, :start2, and :end2—specify the starting (inclusive) and ending (exclusive) indices of substrings in the first and second string arguments. • For example, (string= "foobarbaz" "quuxbarfoo" :start1 3 :end1 6 :start2 4 :end2 7) compares the substring “bar” in the two arguments and returns true. • The :end1 and :end2 arguments can be NIL (or the keyword argument omitted altogether) to indicate that the corresponding substring extends to the end of the string. • For examples: Break 10 [11]> (string= "foobarbaz" "quuxbarfoo" :start1 3 :start2 4 ) NIL Break 10 [11]> (string= "foobar" "quuxbar" :start1 3 :start2 4 ) T
STRING COMPARISONS • The comparators that return true when their arguments differ. • All of them exceptSTRING= and STRING-EQUAL return the index in the first string where the mismatch was detected. (string/= "lisp" "lissome") → 3 • If the first string is a prefix of the second, the return value will be the length of the first string. (string< "lisp" "lisper") → 4 • When comparing substrings, the resulting value is still an index into the string as a whole. • For instance, the following compares the substrings “bar” and “baz” but returns 5 because that’s the index of the rin the first string: (string< "foobar" "abaz" :start1 3 :start2 1) → 5 ;not 2
EXERCISE • please write a function STRCOM, which can read two input strings STR1 and STR2 and check if STR1 is a substring of STR2 or STR2 is a substring of STR1. > (STRCOM) Please input the first string STR1: abcdefghijk Please input the second string STR2: cdefg STR2 is a substring of STR1 from position 2 to position 6. Do you want to check other strings? Y Please input the first string STR1: aaaa Please input the second string STR2: cccaaaaaaccc STR1 is a substring of STR2 from position 3 to position 6. Do you want to check other strings? Y Please input the first string STR1: abcd Please input the second string STR2: ccaacc STR1 is not a substring of STR2 and STR2 is not a substring of STR1. Do you want to check other strings? N NIL