【读书笔记】编程实操-位和字节(七)

目录

一. 位运算

二. 无符号整型数(简单的说 不带正负号的整型数)

        2.1 整型类型的定义

           2.2 Lua中的无符号整型

                        2.2.3 如何处理无符号整型数,请看下面例子

三. 打包和解包二进制数据

        例1. 输出一个指定字符串中所有被打包的字符串


一. 位运算

        与算术运算符不同,位运算符只能用于整型数。位运算符包括 &(按位与)、|(按位或)、~(按位异或)、>>(逻辑右移)、(逻辑左移) 和 一元运算符~(按位取反) 。(注意:在其他一些语言中,异或运算符位^, 而在Lua语言中^ 代表幂运算)

        二进制按位与、按位或、按位异或的理解

-- 下面例子都是用16进制表现
string.format("%x", 0xff & 0xabcd)	--> cd
string.format("%x", 0xff | 0xabcd)	--> abff
string.format("%x", 0xaaaa ~ -1)	--> ffffffffffff5555 
string.format("%x", ~0)		--> ffffffffffffffff

        两个移位操作都会用0填充空出的位,这个行为通常称为逻辑移位。Lua语言没有提供算术右移,即 使用符合位填充空出的位。我们可以通过向下取整除法(floor除法),除以合适的2的整数次幂来实现算术右移(例如,x//16与算术右移4位等价)

        移位数是负数表示向相反的方向移位,即a>>n 与 a:

string.format("%x",0xff << 12)	-->ff000
string.format("%x", 0xff >> -12) --> abff

        如果移位数等于或大于整型表示的位数(标准Lua为64位,精简Lua为32位),由于所有的位都被结果中移出了,所以结果是0:

string.format("%x", -1 << 80) --> 0

二. 无符号整型数(简单的说 不带正负号的整型数)

无符合整型数(百度百科)

        2.1 整型类型的定义

                整型有无符号(unsigned)有符号(signed)两种类型。在默认情况下声明的整型变量都是有符号的类型。

                无符号整型和有符号整型的区别:无符号类型可以存放的正数范围比有符号整型中范围大一倍,因为有符号类型将最高位用来存储符号,而无符号类型全部存储数字

           2.2 Lua中的无符号整型

                        2.2.3 如何处理无符号整型数,请看下面例子

> x = 13835058055282163712	--这是一个比2^63-1 还大的数,所以X是一个无符号整型数
> x --> - 4611686018427387904   
-- 在控制台输出为 一个负数,因为Lua整型默认是有符号整型, 正数部分最大是 2^63-1 ,
--	所以X 比 2^63-1 还大 4611686018427387904 这么多,所以自动转换成负数

                那么如果需要对有符号整数进行处理的话,需要怎么做呢?

                a. 可以使用选项 %u 或 %x 在函数string.format 中指定以无符号整型数进行输出

string.format("%u", x)	--> 13835058055282163712
sting.format("0x%X", x)	--> 0xC000000000000000 (十六进制)

                b. 加法、减法和乘法操作对于有符号整型数和无符号整型数是一样的

string.format("%u", x)	--> 13835058055282163712
string.format("%u", x + 1)	--> 13835058055282163713
string.format("%u", x - 1)	--> 13835058055282163711

                c. 比较运算符 比较 不同符号位的整型数会出现问题,因为有符号整型的整数更小,代表的是负数,

0x7fffffffffffffff < 0x8000000000000000 --> false 

                        Lua5.3提供了函数math.ult 来比较无符号整型数

math.ult(0x7fffffffffffffff, 0x8000000000000000)	--> true

                        或者 在进行有符号比较前先用掩码掩去两个操作数的符号位

mask = 0x8000000000000000
(0x77fffffffffffffff ~ mask) < (0x8000000000000000 ~ mask) --> true

                d. 无符号除法(算法直接用)

function udiv(n, d)
    if d < 0 then
      if math.ult(n, d) then 
        return 0
     else
        return 1
     end
     local q = ((n >> 1) // d) << 1
     local r = n - q * d
     if not math.utl(r, d) then q = q + 1 end
     return q	
    end
end

                 e. 无符号整型数转换为浮点型数(算法直接用)

                要把一个无符号整型数转换位浮点型数,可以先将其转换成有符号整型数,取模纠正结果

u = 11529215046068469760
f = (u + 0.0) % 2^64 
string.format("%.0f"", f)	--> 11529215046068469760

        

                 f. 浮点型数转换为无符号整型数(算法直接用)

f = 0xA000000000000000.0
u = math.tointeger(((f + 2 ^63) % 2^64) - 2^63)
string.format("%x", u)	--> a000000000000000

三. 打包解包二进制数据

        函数 string.pack: 会把值 "打包"为二进制字符串

        函数 string.unpack: 则从字符串中提取这些值

        string.pack 和 string.unpack 的第一个参数是格式化字符串,用于描述如何打包数据。格式化字符串中的每个字母都描述了如何打包/解包一个值

s = string.pack("iii", 3, -27, 450)
> #s	--> 12
> string.unpack("iii",s)	-->3 -27 450 13(即 unpack函数会返回最后一个读取的元素在字符串的位置)

         string.unpack 有一个可选的第三参数,用于指定开始读取的位置

        例1. 输出一个指定字符串中所有被打包的字符串

s = "hello\0Lua\0world\0"
local i = 1
while i <= #s do
    local res
    res, i = string.unpack("z", s, i)
    print(res)
end
--> hello
--> Lua
--> world

                选项 z意味着一个以\0结尾的字符串

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值