未跨越字节的除法
Division not crossing over bytes
我正试图对由2个uint64_t
s组成的uint128_t
进行除法运算。奇怪的是,该函数适用于uint64_t
s,只设置了下限值,上限值为0。我不明白为什么。
这是除法和位移的代码
class uint128_t{
private:
uint64_t UPPER, LOWER;
public:
// lots of stuff
uint128_t operator<<(int shift){
uint128_t out;
if (shift >= 128)
out = uint128_t(0, 0);
else if ((128 > shift) && (shift >= 64))
out = uint128_t(LOWER << (64 - shift), 0);
else if (shift < 64)
out = uint128_t((UPPER << shift) + (LOWER >> (64 - shift)), LOWER << shift);
return out;
}
uint128_t operator<<=(int shift){
*this = *this << shift;
return *this;
}
uint128_t operator/(uint128_t rhs){
// copy of numerator = copyn
uint128_t copyn(*this), quotient = 0;// constructor: uint128_t(T), uint128_t(S, T), uint128_t(uint128_t), etc
while (copyn >= rhs){
// copy of denomiator = copyd
// temp is the current quotient bit being worked with
uint128_t copyd(rhs), temp(1);
// shift the divosr to the highest bit
while (copyn > (copyd << 1)){
copyd <<= 1;
temp <<= 1;
}
copyn -= copyd;
quotient += temp;
}
return quotient;
}
// more stuff
};
请忽略我对记忆管理的公然漠视。
out = uint128_t(LOWER << (64 - shift), 0);
是错误的,应该是shift - 64
。
作为样式说明,ALL_CAPITALS通常仅为常量保留。变量和成员应主要使用小写字母。
试试这个:
// some bit operations stuff
const unsigned char de_brujin_bit_map_64 [] =
{
0,1,2,7,3,13,8,19,4,25,14,28,9,34,20,40,5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
63,6,12,18,24,27,33,39,16,37,45,47,30,53,49,56,62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
};
inline uint8_t trailing_zero_count(uint64_t x) { return x?de_brujin_bit_map_64[(lower_bit(x)*0x0218A392CD3D5DBFL) >> 58]:64; }
inline uint8_t leading_zero_count(uint64_t x) { return x?(63-de_brujin_bit_map_64[(upper_bit(x)*0x0218A392CD3D5DBFL) >> 58]):64; }
inline uint64_t lower_bit(uint64_t x) { return x & -(int64_t&)x; }
inline uint64_t upper_bit(uint64_t x)
{
if(!x) return 0;
x |= x >> 1; x |= x >> 2; x |= x >> 4; x |= x >> 8; x |= x >> 16; x |= x >> 32;
return (x >> 1) + 1;
}
inline uint128_t upper_bit(const uint128_t x)
{
if(x.upper()) return uint128_t(upper_bit(x.upper()), 0);
else return uint128_t(0, upper_bit(x.lower()));
}
inline uint128_t lower_bit(const uint128_t x)
{
if(x.lower()) return uint128_t(0, lower_bit(x.lower()));
else return uint128_t(lower_bit(x.upper()), 0);
}
inline uint8_t trailing_zero_count(const uint128_t& x) { return x.lower()?trailing_zero_count(x.lower()):(64+trailing_zero_count(x.upper())); }
inline uint8_t leading_zero_count(const uint128_t& x) { return x.upper()?leading_zero_count(x.upper()):(64+leading_zero_count(x.lower())); }
// division operator
uint128_t uint128_t::operator/(const uint128_t& rhs) const
{
if(rhs == 0) return uint128_t(0); // !!!! zero division
if(rhs == rhs) return uint128_t(1);
if(rhs > *this) return uint128_t(0);
if(rhs == 1) return *this;
if(!upper_ && !rhs.upper_) return uint128_t(0, lower_/rhs.lower_);
if(lower_bit(rhs) == rhs) return *this >> trailing_zero_count(rhs);
uint128_t result;
uint128_t bit_mask = upper_bit();
uint128_t denom = 1;
do
{
bit_mask >>= 1;
denom <<= 1;
if(*this & bit_mask) denom |= 1;
result <<= 1;
if(denom >= rhs) { denom -= rhs; result |= 1; }
}
while (bit_mask.lower_ != 1);
return result;
}
无论如何,这个版本稍微快一点:)
确保,针对127:进行4000次迭代
uint128_t divident = uint128_t(0xffffffffffffffffULL, 0xffffffffffffffffULL);
uint128_t divisor = 10;
{
uint32_t iter_count = 0;
uint128_t copyn(divident), quotient = 0;
while (copyn >= divisor)
{
++iter_count;
uint128_t copyd(divisor), temp(1);
while ((copyn >> 1) > copyd) { ++iter_count; copyd <<= 1; temp <<= 1; }
copyn -= copyd;
quotient += temp;
}
std::cout << "iterations: " << std::dec << iter_count << std::endl;
}
{
uint32_t iter_count = 0;
uint128_t bit_pos = dtl::bits::upper_bit(divident);
uint128_t tmp = 1, quotient = 0;
do
{
++iter_count;
bit_pos >>= 1;
tmp <<= 1;
if(divident & bit_pos) tmp |= 1;
quotient <<= 1;
if(tmp >= divisor) { tmp -= divisor; quotient |= 1; }
}
while (bit_pos != 1);
std::cout << "iterations: " << std::dec << iter_count << std::endl;
}
相关文章:
- 从不同线程使用int64的不同字节安全吗
- 将Integer转换为4字节的unsined字符矢量(按大端字节顺序)
- 在UNIX系统中使用DIR查找文件的字节大小
- 如何使用Crypto++并为RSA返回可打印的字节/字符数组
- std::当在256字节边界上写入整数时,流的奇怪行为
- 当比特(而不是字节)的顺序至关重要时的持久性
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 如何在文件中查找字节序列
- luaL_dofile在已知良好的字节码上失败,可以使用未编译的版本
- 在除法中不需要四舍五入
- 字节到位运算符重载C++
- 在java中读取c++字节的位字段
- 使用 std::vector::reverse_iterator 将 int 序列化为字节向量?
- 字节真的是最小可寻址单元吗
- struct.error:解压缩 C++ 结构时,解包需要 288 字节的缓冲区
- 读取文件中所有可能的十六进制 16 字节序列并打印每个序列
- 如何使用 OpenCV 解码在两个 UWP 应用之间发送的图像字节?
- 如何将字节数组元素替换为修改的十六进制 ASCII 符号?
- 这个代码如何使用64位乘法和模除法计算字节的奇偶校验
- 未跨越字节的除法