Cookbook:3.数字日期和时间

本文介绍了Python中处理数字和时间的各种方法,包括数值取整、精确小数计算、数值格式化输出、二进制、八进制和十六进制转换、大整数的字节串操作、复数运算、无穷大和NaN处理、分数计算、大型数组处理、矩阵和线性代数、随机选择、时间换算、日期范围计算以及涉及时区的问题。涉及到的模块有decimal、fraction、numpy、random、datetime和pytz等。
摘要由CSDN通过智能技术生成

3.1数值取整

将浮点数取固定的小数位

round(value,ndigits)
round(1.23,1)
#1.2
round(-1.27,1)
#-1.3
round(1.27,1)
#1.3

某个值为整数的一半时,取到离该值最近的偶数,即1.5和2.5都取为2

ndigits可以是负数

a=1627731
round(a,-1)
#1637730
round(a,-3)
#1628000

如果只是将数值以固定的位数输出,使用format

x=1.23456
format(x,'0.2f')
#'1.23'
'value is {:0.3f}'.format(x)
#'value is 1.235'

3.2精确的小数计算

a=4.2
b=2.1
(a+b)==6.3
#False
a+b
#6.300000000001
decimal模块
from decimal import Decimal
a=Decimal('4.2')
b=Decimal('2.1')
a+b
#Decimal('6.3')
from decimal import localcontext
a=Decimal('1.3')
b=Decimal('1.7')
print(a/b)

0.7647058823529411764705882353
with localcontext() as ctx:
    ctx.prec=3
    print(a/b)
0.765

注意原生的浮点数计算快的多,不必为了一丝误差而使用不必要的的包,decimal适用于金融数据。

大数加小数
nums=[1.23e+18,1,-1.23e+18]
sum(nums)
# 0.0
import math
math.fsum(nums)
#1.0

3.3数值的格式化输出

包括控制位数、对齐、包含千位分隔符

format()函数
x=1234.56789
format(x,'0.2f')
#'1234.57'
format(x,'>10.1f')#右对齐,10个字符
'    1234.6'
format(x,'^10.2f')#居中
' 1234.57  '
format(x,',')#加入千分位符
format(x,'0,.1f')#加入千分位符以及位数控制
#'1,234.56789'
#'1,234.6'

若用科学计数法,把f改成e或E

format一般格式为’[<>^]?width[,].(digits)?’

用%操作符作格式化处理
'%0.2f'%x
'1234.57'

没有format这么强大

3.4二进制、八进制、十六进制

bin(),oct(),hex()
x=1234
bin(x)
#'0b10011010010'
oct(x)
#'0o2322'
hex(x)
#'0x4d2'

如果不要前缀,使用format函数:

format(x,'b')
#'10011010010'

如果要产生无负号的值,需要加上最大值来设置比特位的长度,如32进制数:

x=-1234
format(2**32+x,'b')
#'11111111111111111111101100101110'
format(2**32+x,'x')
#'fffffb2e'

将字符串形式的整数转换,需要使用int()函数使用进制

int('4d2',16)
#1234

强大的format和int函数

请确保在python使用八进制加上’0o‘前缀!

3.5字节串中打包和解包大整数

将字符串解包为一个整型数值,将大整数转换成字符串

data=b'\x00\x124v\x00x\x90\xab\x00\xcd\xef\x01\00#\x004'
int.from_bytes()

将字节解释为整数:

len(data)
#16
int.from_bytes(data,'little')
69120565665751139577663547927631761920
int.from_bytes(data,'big')
94525377821947740945920721189797940

将大整数转化为字符串,用x.to_bytes()

其big和little是指定了整数字节是从低位到高位,还是从高位到低位:

x=0x01020304
x.to_bytes(4,'big')
b'\x01\x02\x03\x04'
x.to_bytes(4,'little')
b'\x04\x03\x02\x01'

用struct模块来解包,由于可解包的整数大小有限制,需要解包多个值然后合并

struct模块
import struct
hi, lo=struct.unpack('>QQ',data)
(hi<<64)+l0		#即将data作int.from_bytes(data,'big')
94525377821947740945920721189797940

如果大小不合适会报错,用int.bit_length()

int.bit_length()
x=523**23
x.bit_length()
#208
nbytes,rem=divmod(x.bit_length(),8)	#divmod返回包含商和余数的元组
if rem:
    nbytes+=1

x.to_bytes(nbytes,'little')
b'\x03X\xf1\x82iT\x96\xac\xc7c\x16\xf3\xb9\xcf\x18\xee\xec\x91\xd1\x98\xa2\xc8\xd9R\xb5\xd0'

3.6复数运算

complex(real,imag)函数

也可以通过浮点数加上后缀j

a=complex(2,4)
b=3-5j
#两种一样

#提取实部和虚部
a.real
#2.0
a.imag
#4.0
a.conjugate()	#共轭
#(2-4j)

加减乘除都可以照样运算

如果要执行函数操作,使用cmath模块:

cmath模块
import cmath
cmath.sin(a)
cmath.exp(a)

numpy更可以直接创建复数数组

import numpy as np

a=np.array([2+3j,4+5j,6-7j,8+9j])
#可执行操作

math.sqrt(-1)会报错,使用cmath.sqrt(-1)即可

3.7处理无穷大和NaN

通过float()来创建

a=float('inf')
b=float('-inf')
c=float('nan')

检测这些值

math.isinf() math.isnan()
math.isinf(a)
#True

inf和nan的运算会传播,不会报错

c+23
#nan
math.sqrt(c)
#nan

注意一点nan互不相等

c=float('nan')
d=float('nan')

c==d
#False
c is d
#False

3.8分数的计算

fractions模块
from fractions import Fraction
a=Fraction(5,4)
b=Fraction(7,16)
print(a+b)
27/16

获取分子,分母操作,转换为小数

c=a*b
c.numerator#分子
#35
c.denominator#分母
#64
float(c)
#0.546875

限制分母大小而约简(不是精确值):

y=Fraction(*x.as_integer_ratio())
print(c.limit_denominator(8))
#4/7

#浮点数转化为小数
x=3.75
y=Fraction(*x.as_integer_ratio())
y
#Fraction(15,4)

3.9处理大型数组

numpy内容

在底层,numpy数组的内存分配和c一样,即是大块的连续内存,由同一种类型的数据组成。即使创建巨大的数组

grid=np.zeros(shape=(10000,10000),dtype=float)

numpy数组索引

a[1]#第一行
a[:,1]#第一列
a[1:3,1:3]#分块,也可对其操作
np.where()函数
np.where(condition,x,y)
#满足condition输出x,否则y

3.10矩阵和线性代数

np.matrix
m=np.matrix([[*****]])
m.T
m.I	#逆
numpy.linalg模块
#求行列式
numpy.linalg.det(m)

#求解矩阵方程  mx=v
s=numpy.linalg.solve(m,v)

3.11随机选择

从序列随机挑选,或生成随机数

random模块
import random
values=[1,2,3,4,5]
random.choice(values)
#随机输出

random.sample(values,2)
#多选

randmo.shuffle(values)
#输出打乱的顺序

random.randint(0,10)
#输出随机整数0,10之间

random.random()
#输出0,1间均匀分布浮点数

random.getrandbits(N)
#输出N位随机比特数表示的整数

random还有许多,random.uniform()计算均匀分布值,random.gauss()计算正态分布

一个正态分布测试:

import numpy as np
import matplotlib.pylab as mp

samples = np.random.normal(size=10000)  # 记录成功曲线的数据
# 验证平均值和标准差(接近0和接近1)
print(samples.mean(), samples.std())

# 基本图形参数
mp.figure('Standard Normal', facecolor='lightgray')
mp.title('Standard Normal', fontsize=20)
mp.xlabel("Sample", fontsize=14)
mp.ylabel('Occurrence', fontsize=14)
mp.tick_params(labelsize=10)
mp.grid(axis='y', linestyle=':')  # 只画水平网格线

# 绘制图像(直方图),100表示分成100段,normed表示按照比例显示纵坐标
mp.hist(samples, 100,
        edgecolor='steelblue',
        facecolor='deepskyblue',
        label="Standard Normal")

mp.legend()
mp.show()
-0.005483648486242648 0.9956123423296523

3.12时间换算

datetime模块
from datetime import timedelta
a=timedelta(days=2,hours=6)
b=timedelta(hours=4.5)
c=a+b
datetime.timedelta(days=2, seconds=37800)

from datetime import datetime

from datetime import datetime

a=datatime(2020,9,10)
print(a+timedelta(days=10))
2020-09-20 00:00:00
now=datetime.today()
datetime.datetime(2020, 11, 23, 14, 39, 0, 562000)

更复杂的时间处理,使用dateutil模块

3.13计算上周五

from datetime import datetime,timedelta

weekdays=['Monday','Tuesday','Wednesday','Thursday','Friday','Saturday','Sunday']

def get_previous_byday(daytime,start_date=None):
    if start_date is None:
        start_date=datetime.today()
    day_num=start_date.weekday()
    day_num_target=weekdays.index(daytime)
    days_ago=(7+day_num-day_num_target)%7
    if days_ago ==0:
        days_ago=7
    target_date = start_date -timedelta(days=days_ago)
    return target_date
datetime.today()
datetime.datetime(2020, 11, 23, 14, 54, 18, 742468)
get_previous_byday('Monday')
datetime.datetime(2020, 11, 16, 14, 54, 38, 559828)

3.14找出当月日期范围

需要循环迭代当月的每个日期

datetime.timedelta对象
from datetime import datetime, date, timedelta
import calendar

#date,datetime是不同的对象

def get_month_range(start_date=None):
    if start_date is None:
        start_date = date.today().replace(day=1)	#replace方法将日子设为1,而月份为today的月份

    _, days_in_month = calendar.monthrange(start_date.year, start_date.month)#不需要的参数可跳过
    end_date = start_date + timedelta(days=days_in_month)
    return (start_date,end_date)
a_day=timedelta(days=1)
first_day,last_day=get_month_range()	#month_range返回元组,包含第一个工作日0~6(周一~周日)和本月天数
while first_day<last_day:
    print(first_day)
    first_day+=a_day
#输出为本月日子

3.15将字符串转换为日期

转换为datetime对象

from datetime import datetime
text = '2020-11-20'
y=datetime.strptime(text,'%Y-%m-%d')
z=datetime.now()
diff=z-y
print(diff)
6 days, 16:44:22.649347
datetime.strptime()方法

该方法支持许多格式化代码,%Y 表示4位数年份 ,%m 表示2位数字月份

下面的办法让输出时间更美观:

z
datetime.datetime(2020, 11, 26, 16, 44, 22, 649347)
nice_z = datetime.strftime(z,'%A %B %d, %Y')
nice_z
'Thursday November 26, 2020'

由于strptime是纯python代码实现,效率很低,可自己编一个函数提升性能(前提是知道日期的格式)

from datetime import datetime
def parse_ymd(s):
    year_s, mon_s, day_s = s.split('-')
    return datetime(int(year_s), int(mon_s), int(day_s))

3.16涉及时区的问题

pytz模块
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值