1. decimal---定点数和浮点数的数学运算
作用: 使用定点数和浮点数的小数运算
1. Decimal
备注:浮点数的问题
>>> 0.1 + 0.2
0.30000000000000004
>>> 0.1 + 0.2 == 0.3
False
而使用Decimal可以避免此问题:
>>> import decimal
>>> decimal.Decimal('0.1') + decimal.Decimal('0.2') == decimal.Decimal('0.3')
True
小数值表示为Decimal类的实例.构造函数取一个整数或字符串作为参数.使用浮点数创建Decimal之前,可以先将浮点数转换为一个字符串,使调用 者能够显式的处理值的位数,倘若使用硬件浮点数表示则无法准确的表述.另外,利用类方法from_float()可以转换为精确的小数表示:
import decimal
fmt = '{0:<25} {1:<25}'
print fmt.format('Input', 'Output')
print fmt.format('-' * 25, '-' * 25)
#Integer
print fmt.format(5, decimal.Decimal(5))
#String
print fmt.format('3.14', decimal.Decimal('3.14'))
#Float
f = 0.1
print fmt.format(repr(f), decimal.Decimal(str(f)))
print fmt.format('%.23g' % f,
str(decimal.Decimal.from_float(f))[:25])
解释器显示如下:
>>>
Input Output
------------------------- -------------------------
5 5
3.14 3.14
0.1 0.1
0.10000000000000000555112 0.10000000000000000555111
Decimal还可以由元组创建,其中包含一个符号标志(0表示正,1表示负),数字tuple以及一个整数指数:
>>> import decimal
>>> t = (1, (1, 2, 3), -2)
>>> decimal.Decimal(t)
Decimal('-1.23')
2. 算术运算
Decimal重载了简单的算术运算符:
>>> import decimal
>>> a = decimal.Decimal('5.1')
>>> b = decimal.Decimal('3.14')
>>> a + b
Decimal('8.24')
>>> a - b
Decimal('1.96')
>>> a * b
Decimal('16.014')
>>> a / b
Decimal('1.624203821656050955414012739')
3. 特殊值
Decimal可以表示特殊值:正负无穷大,"不是一个数"和0
>>> import decimal
>>> for value in ['Infinity', 'NaN', '0']:
print decimal.Decimal(value),
Infinity NaN 0
4. 上下文
可以使用一个上下文(context)覆盖某些设置,如保持精度,如何完成取整,错误处理等等.上下文可以应用于一个线程中的所有Decimal实例,或者局部应用于一个小代码区.
当前上下文
要取得当前全局上下文,可以使用getcontext():
import decimal
import pprint
context = decimal.getcontext()
print 'Emax =', context.Emax
print 'Emin =', context.Emin
print 'capitals =', context.capitals
print 'prec =', context.prec
print 'rounding =', context.rounding
print 'flags =', context.flags
print 'traps =', context.traps
解释器显示如下:
>>>
Emax = 999999999
Emin = -999999999
capitals = 1
prec = 28
rounding = ROUND_HALF_EVEN
flags = {<class 'decimal.Underflow'>: 0, <class 'decimal.Subnormal'>: 0, <class 'decimal.Inexact'>: 0, <class 'decimal.Overflow'>: 0, <class 'decimal.InvalidOperation'>: 0, <class 'decimal.Clamped'>: 0, <class 'decimal.DivisionByZero'>: 0, <class 'decimal.Rounded'>: 0}
traps = {<class 'decimal.Underflow'>: 0, <class 'decimal.Subnormal'>: 0, <class 'decimal.Inexact'>: 0, <class 'decimal.Overflow'>: 1, <class 'decimal.InvalidOperation'>: 1, <class 'decimal.Clamped'>: 0, <class 'decimal.DivisionByZero'>: 1, <class 'decimal.Rounded'>: 0}
精度
上下文的prec属性控制着作为算术运算结果所创建的新值的精度.字面量值会按这个属性保持精度:
import decimal
d = decimal.Decimal('0.123456')
for i in range(4):
decimal.getcontext().prec = i
print i, ':', d, d * 1
解释器显示如下:
>>>
0 : 0.123456 0
1 : 0.123456 0.1
2 : 0.123456 0.12
3 : 0.123456 0.123
取整
取整有多种选择,以保证值在所需精度范围内:
ROUND_CEILING:总是趋向无穷大向上取整
ROUND_DOWN:总是趋向0取整
ROUND_FLOOR:总是趋向负无穷大向下取整
ROUND_HALF_DOWN:四舍五入式取整
ROUND_HALF_EVEN:类似ROUND_HALF_DOWN.不过如果最后一个有效数字值为5,则会检查前一位.偶数值会导致结果向下取整,奇数值导致结果向上取整.
ROUND_HALF_UP:五舍六入式取整(最后一位为5,则向0的方向取整)
ROUND_UP:朝0的反方向取整
ROUND_05UP:如果最后一位是0或5,则朝0的反方向取整,否则向0取整.
import decimal
context = decimal.getcontext()
ROUNDING_MODES = [
'ROUND_CEILING',
'ROUND_DOWN',
'ROUND_FLOOR',
'ROUND_HALF_DOWN',
'ROUND_HALF_EVEN',
'ROUND_HALF_UP',
'ROUND_UP',
'ROUND_05UP',
]
header_fmt = '{:10}' + ' '.join(['{:^8}'] * 6)
print header_fmt.format(' ',
'1/8 (1)', '-1/8 (1)',
'1/8 (2)', '-1/8 (2)',
'1/8 (3)', '-1/8 (3)',
)
for rounding_mode in ROUNDING_MODES:
print '{0:10}'.format(rounding_mode.partition('_')[-1]),
for precision in [1, 2, 3]:
context.prec = precision
context.rounding = getattr(decimal, rounding_mode)
value = decimal.Decimal(1) / decimal.Decimal(8)
print '{0:^8}'.format(value),
value = decimal.Decimal(-1) / decimal.Decimal(8)
print '{0:^8}'.format(value),
print
解释器显示如下:
>>>
1/8 (1) -1/8 (1) 1/8 (2) -1/8 (2) 1/8 (3) -1/8 (3)
CEILING 0.2 -0.1 0.13 -0.12 0.125 -0.125
DOWN 0.1 -0.1 0.12 -0.12 0.125 -0.125
FLOOR 0.1 -0.2 0.12 -0.13 0.125 -0.125
HALF_DOWN 0.1 -0.1 0.12 -0.12 0.125 -0.125
HALF_EVEN 0.1 -0.1 0.12 -0.12 0.125 -0.125
HALF_UP 0.1 -0.1 0.13 -0.13 0.125 -0.125
UP 0.2 -0.2 0.13 -0.13 0.125 -0.125
05UP 0.1 -0.1 0.12 -0.12 0.125 -0.125
局部上下文
我们可以使用with来创建上下文:
>>> import decimal
>>> with decimal.localcontext() as c:
c.prec = 2
print decimal.Decimal('1') / 3
0.33
>>> decimal.Decimal('1') / 3
Decimal('0.333') #默认为28位,但之前设置为4位精度了
我们可以通过setcontext来重新设置精度:
>>> decimal.setcontext(decimal.DefaultContext)
>>> decimal.Decimal('1.0') / decimal.Decimal('3.0')
Decimal('0.3333333333333333333333333333')
各实例的上下文
上下文还可以用来构造Decimal实例,然后可以从这个上下文继承精度和转换的取整参数:
import decimal
#Set up a context with limited precision
c = decimal.getcontext().copy()
c.prec = 3
#Create our constant
pi = c.create_decimal('3.1415')
#The constant value is rounded off
print 'PI :', pi
#The result of using the constant uses the global context
print 'RESULT:', decimal.Decimal('2.01') * pi
解释器显示如下:
>>>
PI : 3.14
RESULT: 6.3114
线程
"全局"上下文实际上是线程本地上下文,所以完全可以使用不同的值分别配置各个线程.
import decimal
import threading
from Queue import PriorityQueue
class Multiplier(threading.Thread):
def __init__(self, a, b, prec, q):
self.a = a
self.b = b
self.prec = prec
self.q = q
threading.Thread.__init__(self)
def run(self):
c = decimal.getcontext().copy()
c.prec = self.prec
decimal.setcontext(c)
self.q.put((self.prec, a * b))
return
a = decimal.Decimal('3.14')
b = decimal.Decimal('1.234')
q = PriorityQueue()
threads = [Multiplier(a, b, i, q) for i in range(1, 6)]
for t in threads:
t.start()
for t in threads:
t.join()
for i in range(5):
prec, value = q.get()
print prec, '\t', value
解释器显示如下:
>>>
1 4
2 3.9
3 3.87
4 3.875
5 3.8748
2. fractions---有理数
作用:实现了一个类来处理有理数
1. 创建Fraction实例
可以通过分子/分母方式创建
>>> import fractions
>>> for n, d in [(1, 2), (2, 4), (3, 6)]:
print fractions.Fraction(n, d),
1/2 1/2 1/2
也可以通过字符串方式表示:
>>> for s in ['1/2', '2/4', '3/6']:
print fractions.Fraction(n, d),
1/2 1/2 1/2
甚至可以使用小数或浮点数来表示:
>>> for s in ['0.5', '1.5', '2.0']:
print fractions.Fraction(s),
1/2 3/2 2
但是不推荐直接使用浮点数来表示:
>>> for v in [0.1, 0.5, 1.5, 2.0]:
print fractions.Fraction(v)
3602879701896397/36028797018963968
1/2
3/2
2
>>> for v in ['0.1', '0.5', '1.5', '2.0']:
print fractions.Fraction(v)
1/10
1/2
3/2
2
2. 算术运算
fractions支持一般的算术运算.
>>> import fractions
>>> f1 = fractions.Fraction(1, 2)
>>> f2 = fractions.Fraction(3, 4)
>>> f1 + f2
Fraction(5, 4)
>>> f1 - f2
Fraction(-1, 4)
>>> f1 * f2
Fraction(3, 8)
>>> f1 / f2
Fraction(2, 3)
3. 近似值
Fraction有一个有用的特性,它能够将一个浮点数转换为一个近似的有理数值
import fractions
import math
print 'PI =', math.pi
f_pi = fractions.Fraction(str(math.pi))
print 'No limit =', f_pi
for i in [1, 6, 11, 60, 70, 90, 100]:
limited = f_pi.limit_denominator(i)
print '{0:8} = {1}'.format(i, limited)
解释器显示如下:
>>>
PI = 3.14159265359
No limit = 314159265359/100000000000
1 = 3
6 = 19/6
11 = 22/7
60 = 179/57
70 = 201/64
90 = 267/85
100 = 311/99
3. random---伪随机数生成器
作用:实现了多种类型的伪随机数生成器
1. 生成随机数
使用random生成一个0<=n<1的随机数.而uniform(m, n)等价于m + (n - m) * random()的返回值:
>>> import random
>>> for i in range(5):
print '%04.3f' % random.random(),
0.178 0.638 0.573 0.031 0.491
>>> for i in range(5):
print '%04.3f' % random.uniform(1, 100),
15.672 19.745 32.444 56.909 98.970
2. 指定种子
默认情况下,程序是通过当前时间作为种子的,所以每次生成的随机数都不一样.但是如果我们指定了种子,则每次生成的随机数就是一样的:
>>> import random
>>> random.seed(1)
>>> for i in range(5):
print '%04.3f' % random.random(),
0.134 0.847 0.764 0.255 0.495
>>> random.seed(1)
>>> for i in range(5):
print '%04.3f' % random.random(),
0.134 0.847 0.764 0.255 0.495
3. 保存状态
我们可以通过setstate来保存状态.通过getstate来获取当前状态:
>>> import random
>>> random.random()
0.4494910647887381
>>> state = random.getstate()
>>> random.random()
0.651592972722763
>>> random.random()
0.7887233511355132
>>> random.setstate(state)
>>> random.random()
0.651592972722763
4. 随机整数
random()将生成浮点数.生成整数的话,使用randint()更加方便,而使用randrange可在一定的范围内生成整数:
>>> import random
>>> random.randint(1, 100)
79
>>> random.randrange(0, 101, 5)
85
5. 选择随机元素
通过choice函数来从一个序列中随机选择元素:
import random
import itertools
outcomes = {'heads': 0,
'tails': 0,
}
sides = outcomes.keys()
for i in range(10000):
outcomes[random.choice(sides)] += 1
print 'Heads:', outcomes['heads']
print 'Tails:', outcomes['tails']
解释器显示如下:
>>>
Heads: 4907
Tails: 5093
6. 排列
模拟扑克牌时候,无法使用choice,因为会导致同一张牌被发出两次.我们可以使用shuffle()来洗牌,然后发牌时候删除所发的牌:
import random
import itertools
FACE_CARDS = {'J', 'Q', 'K', 'A'}
SUITS = {'H', 'D', 'C', 'S'}
def new_deck():
return list(itertools.product(
itertools.chain(range(2, 11), FACE_CARDS),
SUITS,
))
def show_deck(deck):
p_deck = deck[:]
while p_deck:
row = p_deck[:13]
p_deck = p_deck[13:]
for j in row:
print '%2s%s' % j,
print
#make a new deck, with the cards in order
deck = new_deck()
print 'Initial deck'
show_deck(deck)
#shuffle the deck to randomize the order
random.shuffle(deck)
print '\nShuffled deck:'
show_deck(deck)
#deal 4 hands of 5 cards each
hands = [[], [], [], []]
for i in range(5):
for h in hands:
h.append(deck.pop())
#show the hands
print '\nhands:'
for n, h in enumerate(hands):
print '%d:' % (n + 1),
for c in h:
print '%2s%s' % c,
print
#show the remaining deck
print '\nremaining deck:'
show_deck(deck)
解释器显示如下:
>>>
Initial deck
2H 2S 2C 2D 3H 3S 3C 3D 4H 4S 4C 4D 5H
5S 5C 5D 6H 6S 6C 6D 7H 7S 7C 7D 8H 8S
8C 8D 9H 9S 9C 9D 10H 10S 10C 10D AH AS AC
AD QH QS QC QD KH KS KC KD JH JS JC JD
Shuffled deck:
2D 4C 2C 3D 8C 2H AD 7S 9S KC JD 6C 10H
3H 9H 5C QD QH AH 4H QC 9D 9C JH JS KS
KH 7H 4S 3S 5D 8D 5H QS 7C 3C 2S AC AS
5S 6D 6S 6H 8H 4D 8S JC 10S 7D 10C 10D KD
hands:
1: KD 10S 8H 5S 3C
2: 10D JC 6H AS 7C
3: 10C 8S 6S AC QS
4: 7D 4D 6D 2S 5H
remaining deck:
2D 4C 2C 3D 8C 2H AD 7S 9S KC JD 6C 10H
3H 9H 5C QD QH AH 4H QC 9D 9C JH JS KS
KH 7H 4S 3S 5D 8D
7. 采样
sample()函数可以生成无重复值的样本,且不会修改输入序列:
>>> import random
>>> a = []
>>> for i in range(10000):
a.append(random.randint(1, 100))
>>> random.sample(a, 5)
[98, 40, 57, 85, 90]
8. 多个并发生成器
random包括一个Random实例来操作:
import random
import time
print 'Default initializiation:\n'
r1 = random.Random()
r2 = random.Random()
for i in range(3):
print '%04.3f %04.3f' % (r1.random(), r2.random())
print '\nSame seed:\n'
seed = time.time()
r1 = random.Random(seed)
r2 = random.Random(seed)
for i in range(3):
print '%04.3f %04.3f' % (r1.random(), r2.random())
解释器显示如下:
>>>
Default initializiation:
0.010 0.206
0.087 0.196
0.049 0.780
Same seed:
0.339 0.339
0.911 0.911
0.583 0.583
往往random使用本机时间作为种子.但是我们可以使用jumpahead来调整生成器的初始状态:
import random
import time
print 'Default initializiation:\n'
r1 = random.Random()
r2 = random.Random()
r2.setstate(r1.getstate())
r2.jumpahead(1024) #根据1024来调整随机数的产生
for i in range(3):
print '%04.3f %04.3f' % (r1.random(), r2.random())
解释器显示如下:
>>>
Default initializiation:
0.593 0.393
0.319 0.854
0.986 0.676
4. math---数学函数
作用:提供函数完成特殊的数学运算
1. 特殊常量
例如pi和e的值:
>>> import math
>>> math.pi
3.141592653589793
>>> math.e
2.718281828459045
2. 测试异常值
有两类异常值:1是INF(无穷大). 2是NaN(不是一个数)
>>> a = 10.0 ** 200
>>> a
1e+200
>>> a * a
inf
但是直接处理指数操作溢出会报异常:
>>> import math
>>> 10.0 ** 20000
Traceback (most recent call last):
File "<pyshell#102>", line 1, in <module>
10.0 ** 20000
OverflowError: (34, 'Result too large')
而用INF来计算则得到NaN:
>>> b
inf
>>> b / b
nan
3. 转换为整数
math模块包括三个函数用于将浮点数值转换为整数.
trunc():截断小数点后的数字,只留下构成这个值整数部分的有效数字.
floor():将其输入转换为不大于它的最大整数
ceil():生成按顺序排在这个输入值之后的最小整数.
import math
HEADINGS = {'i', 'int', 'trunk', 'floor', 'ceil'}
print '{:^5} {:^5} {:^5} {:^5} {:^5}'.format(*HEADINGS)
print '{:-^5} {:-^5} {:-^5} {:-^5} {:-^5}'.format('', '', '', '', '',)
fmt = ' '.join(['{:5.1f}'] * 5)
TEST_VALUES = [-1.5,
-0.8,
-0.5,
-0.2,
0,
0.2,
0.5,
0.8,
1,
]
for i in TEST_VALUES:
print fmt.format(i, int(i), math.trunc(i), math.floor(i), math.ceil(i))
解释器生成如下:
>>>
int i floor trunk ceil
----- ----- ----- ----- -----
-1.5 -1.0 -1.0 -2.0 -1.0
-0.8 0.0 0.0 -1.0 -0.0
-0.5 0.0 0.0 -1.0 -0.0
-0.2 0.0 0.0 -1.0 -0.0
0.0 0.0 0.0 0.0 0.0
0.2 0.0 0.0 0.0 1.0
0.5 0.0 0.0 0.0 1.0
0.8 0.0 0.0 0.0 1.0
1.0 1.0 1.0 1.0 1.0
4. 其他表示
modf()取一个浮点数,并返回一个tuple,其中包含这个输入值的小数和整数部分:
>>> import math
>>> math.modf(5 / 2.0)
(0.5, 2.0)
frexp()返回一个浮点数的尾数和指数:
import math
print '{:^7} {:^7} {:^7}'.format('x', 'm', 'e')
print '{:-^7} {:-^7} {:-^7}'.format('', '', '')
for x in [0.1, 0.5, 4.0]:
m, e = math.frexp(x)
print '{:7.2f} {:7.2f} {:7d}'.format(x, m, e)
解释器显示如下:
>>>
x m e
------- ------- -------
0.10 0.80 -3
0.50 0.50 0
4.00 0.50 3
frexp()使用公式x = m * 2 ** e,并返回值m和e
而ldexp()与frexp()正好相反:
import math
print '{:^7} {:^7} {:^7}'.format('x', 'm', 'e')
print '{:-^7} {:-^7} {:-^7}'.format('', '', '')
for m, e in [(0.8, -3),
(0.5, 0),
(0.5, 3),
]:
x = math.ldexp(m, e)
print '{:7.2f} {:7d} {:7.2f}'.format(m, e, x)
解释器显示如下:
>>>
x m e
------- ------- -------
0.80 -3 0.10
0.50 0 0.50
0.50 3 4.00
5. 常用计算
一般对浮点数的运算都会存在误差.在计算总和的时候,我们应该使用fsum()来计算:
>>> import math
>>> values = [0.1] * 10
>>> values
[0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1]
>>> sum(values)
0.9999999999999999
>>> math.fsum(values)
1.0
factorial(): 计算阶乘(n!)
>>> math.factorial(5)
120
gamma():计算阶乘(n-1)!,不同于factorial(),它可以计算实数
>>> math.gamma(5.2)
32.578096050331354
lgamma():对输入值求gamma()所得绝对值的自然对象
import math
for i in [0, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6]:
try:
print '{:2.1f} {:.20f} {:.20f}'.format(
i,
math.lgamma(i),
math.log(math.gamma(i)),
)
except ValueError, err:
print 'Error computing lgamma(%s):' % i, err
解释器显示如下:
>>>
Error computing lgamma(0): math domain error
1.1 -0.04987244125984036103 -0.04987244125983997245
2.2 0.09694746679063825923 0.09694746679063866168
3.3 0.98709857789473387513 0.98709857789473409717
4.4 2.31610349142485727469 2.31610349142485727469
5.5 3.95781396761871651080 3.95781396761871606671
6.6 5.84268005527463252236 5.84268005527463252236
而我们也可以使用fmod()来计算求余:
>>> import math
>>> math.fmod(-5.0, 2)
-1.0
>>> -5.0 % 2
1.0
6. 指数和对数
pow(x, y): x ** y
>>> import math
>>> pow(2.1, 3)
9.261000000000001
sqrt(x):计算平方根
>>> import math
>>> math.sqrt(10)
3.1622776601683795
log(x, y):y默认为e
>>> import math
>>> math.log(8)
2.0794415416798357
>>> math.log(8, 2)
3.0
>>> math.log(0.5, 2)
-1.0
log10(x):等于log(x, 10),但是比log(x, 10)更加精确
>>> math.log10(123)
2.089905111439398
>>> math.log(123, 10)
2.0899051114393976
exp(x):等于pow(e, x),但是比pow(e, x)更加精确.
>>> math.exp(3)
20.085536923187668
>>> math.pow(math.e, 3)
20.085536923187664
7. 角
radians(): 把度转换为弧度
degrees(): 把弧度转换为度
>>> deg = [0, 30, 60, 90, 180, 270, 360]
>>> import math
>>> rad = [math.radians(x) for x in deg]
>>> rad
[0.0, 0.5235987755982988, 1.0471975511965976, 1.5707963267948966, 3.141592653589793, 4.71238898038469, 6.283185307179586]
>>> [math.degrees(x) for x in rad]
[0.0, 29.999999999999996, 59.99999999999999, 90.0, 180.0, 270.0, 360.0]
8. 三角函数
我们可以使用sin,cos和tan等三角函数:
import math
print 'Degrees Radians Sine Cosine Tangent'
print '------- ------- ------- ------- -------'
fmt = ' '.join(['%7.2f'] * 5)
for deg in range(0, 361, 30):
rad = math.radians(deg)
if deg in (90, 270):
t = float('inf')
else:
t = math.tan(rad)
print fmt % (deg, rad, math.sin(rad), math.cos(rad), t)
解释器显示如下:
>>>
Degrees Radians Sine Cosine Tangent
------- ------- ------- ------- -------
0.00 0.00 0.00 1.00 0.00
30.00 0.52 0.50 0.87 0.58
60.00 1.05 0.87 0.50 1.73
90.00 1.57 1.00 0.00 inf
120.00 2.09 0.87 -0.50 -1.73
150.00 2.62 0.50 -0.87 -0.58
180.00 3.14 0.00 -1.00 -0.00
210.00 3.67 -0.50 -0.87 0.58
240.00 4.19 -0.87 -0.50 1.73
270.00 4.71 -1.00 -0.00 inf
300.00 5.24 -0.87 0.50 -1.73
330.00 5.76 -0.50 0.87 -0.58
360.00 6.28 -0.00 1.00 -0.00
而我们也可以通过反三角函数:asin,acos,atan来计算:
>>> import math
>>> for r in [0, 0.5, 1]:
print 'arcsine(%.1f) = %5.2f' % (r, math.asin(r))
print 'arccosine(%.1f) = %5.2f' % (r, math.acos(r))
print 'arctangent(%.1f) = %5.2f' % (r, math.atan(r))
print
arcsine(0.0) = 0.00
arccosine(0.0) = 1.57
arctangent(0.0) = 0.00
arcsine(0.5) = 0.52
arccosine(0.5) = 1.05
arctangent(0.5) = 0.46
arcsine(1.0) = 1.57
arccosine(1.0) = 0.00
arctangent(1.0) = 0.79
9. 双曲函数
双曲函数通过sinh(),cosh()和tanh()来实现:
import math
print '{:^6} {:^6} {:^6} {:^6}'.format('X', 'sinh', 'cosh', 'tanh',)
print '{:-^6} {:-^6} {:-^6} {:-^6}'.format('', '', '', '')
fmt = ' '.join(['{:6.4f}'] * 4)
for i in range(0, 11, 2):
x = i / 10.0
print fmt.format(x, math.sinh(x), math.cosh(x), math.tanh(x))
解释器显示如下:
>>>
X sinh cosh tanh
------ ------ ------ ------
0.0000 0.0000 1.0000 0.0000
0.2000 0.2013 1.0201 0.1974
0.4000 0.4108 1.0811 0.3799
0.6000 0.6367 1.1855 0.5370
0.8000 0.8881 1.3374 0.6640
1.0000 1.1752 1.5431 0.7616