在C++中实现定点运算时移位是什么意思?

问题描述 投票:0回答:2

我在理解定点算术及其在 C++ 中的实现方面遇到问题。我试图理解这段代码:

#define scale 16

int DoubleToFixed(double num){
    return num * ((double)(1 << scale));
}

double FixedToDoble(int num){
    return (double) num / (double)(1 << scale);
}

double IntToFixed(int num){
    return x << scale
}

我试图准确理解我们转变的原因。我知道向右移动基本上是将该数字乘以 2x,其中 x 是我们要移动或缩放的位置数,向左移动基本上是除以 2x

但是为什么我们从 int 转换为定点时需要移位呢?

c++ fixed-point byte-shifting
2个回答
2
投票

定点格式将数字表示为整数乘以固定小数位数。通常,比例尺是某个基数 b 的某个幂 e,因此整数 f 将代表数字 fbe

在所示代码中,比例为 2−16 或 1/65,536。 (将移位量称为

scale
是用词不当;16,或者更确切地说 -16,是指数。)因此,如果表示数字的整数是 81,920,则表示的值是 81,920•2−16 = 1.25。

例程

DoubleToFixed
通过乘以标度的倒数将浮点数转换为定点格式;它乘以 65,536。

例程

FixedToDouble
通过乘以小数位数或等效地除以其倒数,将数字从固定格式转换为浮点数;它除以 65,536。

IntToFixed
DoubleToFixed
执行相同的操作,除了
int
输入之外。


-1
投票

定点算术的原理是将数字表示为非常小的“基数”的整数倍。您的案例使用

1/(1<<scale)
为基数,又名
1/65536
,大约为
0.00001525878

因此,数字 3.141592653589793 可以表示为 205887.416146 个

1/65536
单位,因此将作为整数值 205887 存储在内存中(由于转换期间的舍入,实际上是 3.14158630371)。

计算小数值到定点转换的方法只需将该值除以基数:

3.141592653589793 / (1/65536) = 205887.416146
。 (值得注意的是,这减少到
3.141592653589793  * 65536 = 205887.416146
)。然而,由于这涉及到二的幂。乘以 2 的幂与简单地左移那么多位相同。因此,只需左移
2^16
位即可更快地计算
65536
(又名
16
)的乘法。这真的快,这就是为什么大多数定点计算使用二的倒数幂作为基础的原因。

由于无法移动

float
值,您的方法会将基数转换为
float
并进行浮点乘法,但其他方法(例如定点乘法和除法本身)可以利用此功能快捷方式。

理论上,可以使用浮点移位来比简单的浮点乘法更快地执行转换函数,但最有可能的是,编译器实际上已经在幕后这样做了。

某些代码使用 10 的反幂作为基数也很常见,主要是为了金钱,通常使用

0.01
为基数,但是这些代码不能使用单次移位作为快捷方式,并且必须做较慢的数学。乘以 100 的一种捷径是
value<<6 + value<<5 + value<<2
(这实际上是
value*64+value*32+value*4
,即
value*(64+32+4)
,即
value*100
),但三移三加有时比一次乘法更快。如果 100 是编译时间常数,编译器已经在幕后执行此快捷方式,所以一般来说,没有人再编写这样的代码了。

© www.soinside.com 2019 - 2024. All rights reserved.