数值类型

简介: 数值类型

数值类型分为整数浮点数定点数三类。


整数——Int

在普遍的观念中,常用 TinyintSmallintIntBigint 指代整数的不同取值范围。而 ClickHouse 则直接使用 Int8Int32Int64 指代 4 种大小的 Int 类型,其末尾的数字正好表明了占用字节的大小(8位=1字节),具体信息如下所示:

名称 大小(字节) 范围 普遍观念
Int8 1 [-128, 127] Tinyint
Int16 2 [-32768, 32767] Smallint
Int32 4 [-2147483648, 2147483647] Int
Int64 8 [-9223372036854775808, 9223372036854775807] Bigint


ClickHouse 支持无符号的整数,使用前缀U 表示,具体信息如下所示:

名称 大小(字节) 范围 普遍观念
UInt8 1 [0, 255] Tinyint Unsigned
UInt16 2 [0, 65535] Smallint Unsigned
UInt32 4 [0, 4294967295] Int Unsigned
UInt64 8 [0, 18446744073709551615] Bigint Unsigned


浮点数——Float

与整数类似, ClickHouse 直接使用 Float32Float64 代表单精度浮点数以及双精度浮点数,具体信息如下所示:

名称 大小(字节) 有效精度(位数) 普遍观念
Float32 4 7 Float
Float64 8 16 Double


在使用浮点数的时候,应当要意识到他是有限精度的。假如,分别对 Float32Float64 写入超过有效精度的数值,就会出现数据误差,例如将拥有 20 位小数的数值分别写入 Float32Float64 时,就会出现数据误差。


$ SELECT toFloat32('0.12345678901234567890') as a, toTypeName(a)
┌──────────a─┬─toTypeName(toFloat32('0.12345678901234567890'))─┐
│ 0.12345679 │ Float32                                         │
└────────────┴─────────────────────────────────────────────────┘
$ SELECT toFloat64('0.12345678901234567890') as a, toTypeName(a)
┌───────────────────a─┬─toTypeName(toFloat64('0.12345678901234567890'))─┐
│ 0.12345678901234568 │ Float64                                         │
└─────────────────────┴─────────────────────────────────────────────────┘点击复制复制失败已复制

可以发现, Float32 从小数点后第 8 位起以及 Float64 从小数点后第 17 位起,都产生了数据溢出。


正无穷、负无穷以及非数字

ClickHouse 的浮点数支持正无穷负无穷以及非数字的表达方式。

-- 正无穷:
$ SELECT 0.8 / 0
┌─divide(0.8, 0)─┐
│            inf │
└────────────────┘
-- 负无穷:
$ SELECT -0.8 / 0
┌─divide(-0.8, 0)─┐
│            -inf │
└─────────────────┘
-- 非数字:
$ SELECT 0 / 0
┌─divide(0, 0)─┐
│          nan │
└──────────────┘点击复制复制失败已复制


定点数——Decimal

如果要求更高精度的数值运算,则需要使用定点数ClickHouse 提供了 Decimal32Decimal64Decimal128 三种精度的定点数。可以通过两种形式声明定点:简写方式有 Decimal32(S)Decimal64(S)Decimal128(S) 三种,原生方式为 Decimal(P, S) ,其中:

  • P代表精度,决定总数(整数部分+小数部分),取值范围是1~38
  • S代表规模,决定小数位数,取值范围是0~P


简写方式与原生方式的对应关系如下所示:

名称 等效声明 范围
Decimal32(S) Decimal(1~9, S) [-10^{9-S}, 10^{9-S}][109S,109S]
Decimal64(S) Decimal(10~18, S) [-10^{18-S}, 10^{18-S}][1018S,1018S]
Decimal128(S) Decimal(19~38, S) [-10^{38-S}, 10^{38-S}][1038S,1038S]


在使用两个不同精度的定点数进行四则运算的时候,他们的小数点位数 S 会发生变化。在进行加法运算时, S最大值

$ SELECT toDecimal64(2, 4) + toDecimal32(2, 2)
┌─plus(toDecimal64(2, 4), toDecimal32(2, 2))─┐
│                                     4.0000 │
└────────────────────────────────────────────┘点击复制复制失败已复制


提示

toDecimal64(2, 4)toDecimal32(2, 2) 相加后 S=4


在进行减法运算时,其规则与加法相同, S 同样会取最大值

$ SELECT toDecimal32(4, 4) - toDecimal64(2, 2)
┌─minus(toDecimal32(4, 4), toDecimal64(2, 2))─┐
│                                      2.0000 │
└─────────────────────────────────────────────┘点击复制复制失败已复制


在进行乘法运算时, S两者之和

$ SELECT toDecimal64(2, 4) * toDecimal32(2, 2)
┌─multiply(toDecimal64(2, 4), toDecimal32(2, 2))─┐
│                                       4.000000 │
└────────────────────────────────────────────────┘点击复制复制失败已复制


提示

toDecimal64(2, 4)toDecimal32(2, 2) 相乘后 S=4+2=6


在进行除法运算时, S被除数的值,此时要求被除数S必须大于除数S,否则会报错

$ SELECT toDecimal64(2, 4) / toDecimal32(2, 2)
┌─divide(toDecimal64(2, 4), toDecimal32(2, 2))─┐
│                                       1.0000 │
└──────────────────────────────────────────────┘点击复制复制失败已复制


提示

toDecimal64(2, 4)toDecimal32(2, 2) 相除后 S=4

定点数四则运算后,精度变化规则:

名称 规则
加法 S=max(S1, S2)
减法 S=max(S1, S2)
乘法 S=S1+S2
除法 S=S1 ( S1 为被除数, S1/S2 )(S1范围>=S2范围)


在使用定点数时还有一点值得注意:由于现代计算器只支持 32 位和 64CPU ,所以 Decimal128 是在软件层面模拟实现的,它的速度会明显慢与 Decimal32Decimal64

目录
相关文章
|
3月前
读取7个数(1—50)的整数值
【10月更文挑战第10天】读取7个数(1—50)的整数值。
37 4
|
7月前
|
C#
C#数值类型介绍及示例
C#数值类型介绍及示例
|
8月前
输出格式:限定小数位数
该内容介绍了在输出小数时如何限定小数位数,使用`%.nf`格式化占位符,其中`n`是所需的小数位数。示例代码展示了`%.2f`用于输出1.1为1.10。此外,可以结合限定宽度占位符一起使用。
46 3
|
8月前
|
SQL 存储 关系型数据库
数值类型
数值类型。
37 1
不用数组求多个数的最小值
不用数组求多个数的最小值
53 0
水仙花数(加扩展自幂数)
水仙花数(加扩展自幂数)
130 0
求两个数二进制中不同位的个数
题目内容:两个int(32)整数m和n的二进制表达中,有多少个位(bit)不同? 输入例子: 1999 2299 输出例子: 7
求两个数的二进制数中不同位的个数
两个整数进行异或的结果是:相同位异或结果为0,不同位异或结果为1,进一步将问题转化为求这两个整数异或结果的二进制位为1的个数即所求两个数二进制数中不同位的合数。
|
C++
C++怎么求三个数的最大值?
C++98的老码农们,应该都知道std::max() 函数可以从两个数中求最大值。
1905 0
C++怎么求三个数的最大值?

热门文章

最新文章