Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/151.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 非标准基上的算法_C++_C++11_Integer Arithmetic - Fatal编程技术网

C++ 非标准基上的算法

C++ 非标准基上的算法,c++,c++11,integer-arithmetic,C++,C++11,Integer Arithmetic,我试图将我的类转换为能够使用数字,而不仅仅是每个数字8位。我偶然发现了一个奇怪的问题:我能够使用uint16\u t 用于我的基本数字类型,但不是uint32\u t。我的代码将返回错误的结果。我用来查找错误的示例是0x1111111*0x1111111111,它应该是0x123456789abcdf00fedcba987654321。但是,我得到了0x123456789abcdf0fedcba987654321 我认为我已经更改了所有硬编码类型,因此更改基本数字类型并不重要,但显然不重要 以下

我试图将我的类转换为能够使用数字,而不仅仅是每个数字8位。我偶然发现了一个奇怪的问题:我能够使用
uint16\u t
用于我的基本数字类型,但不是
uint32\u t
。我的代码将返回错误的结果。我用来查找错误的示例是
0x1111111*0x1111111111
,它应该是
0x123456789abcdf00fedcba987654321
。但是,我得到了
0x123456789abcdf0fedcba987654321

我认为我已经更改了所有硬编码类型,因此更改基本数字类型并不重要,但显然不重要

以下是相关代码:

typedef uint32_t                          digit;            // original code uses uint8_t; uint16_t works too
typedef uint64_t                          double_digit;     // int type to hold overflow values

typedef std::deque <digit>                base;

const digit NEG1 = -1;                    // uint8_t -> 255, uint32_t -> 4294967295
const digit BITS = sizeof(digit) << 3;    // sizeof gives the number of bytes, so multiply that by 8 to get the number of bits
const digit HIGH_BIT = 1 << (BITS - 1);   // uint8_t -> 128

        // left bit shift. sign is maintained
        integer operator<<(uint64_t shift){
            if (!*this || !shift)
                return *this;
            base out = digits;
            for(uint64_t i = 0; i < (shift / BITS); i++)
                out.push_back(0);
            shift %= BITS;
            if (shift){
                out.push_back(0);
                return integer(out, _sign) >> (BITS - shift);
            }
            return integer(out, _sign);
        }

        // right bit shift. sign is maintained
        integer operator>>(uint64_t shift){
            if (shift >= bits())
                return integer(0);
            base out = digits;
            for(uint64_t i = 0; i < (shift / BITS); i++)
                out.pop_back();
            shift %= BITS;
            if (shift){
                base v;
                for(d_size i = out.size() - 1; i != 0; i--)
                    v.push_front(((out[i] >> shift) | (out[i - 1] << (BITS - shift))) & NEG1);
                v.push_front(out[0] >> shift);
                out = v;
            }
            return integer(out, _sign);
        }

        // operator+ calls this
        integer add(integer & lhs, integer & rhs){
            base out;
            base::reverse_iterator i = lhs.digits.rbegin(), j = rhs.digits.rbegin();
            bool carry = false;
            double_digit sum;
            for(; ((i != lhs.digits.rend()) && (j != rhs.digits.rend())); i++, j++){
                sum = *i + *j + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            for(; i != lhs.digits.rend(); i++){
                sum = *i + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            for(; j != rhs.digits.rend(); j++){
                sum = *j + carry;
                out.push_front(sum);
                carry = (sum > NEG1);
            }
            if (carry)
                out.push_front(1);
            return integer(out);
        }

        // operator* calls this
        // Long multiplication
        integer long_mult(integer & lhs, integer & rhs){
            unsigned int zeros = 0;
            integer row, out = 0;
            for(base::reverse_iterator i = lhs.digits.rbegin(); i != lhs.digits.rend(); i++){
                row.digits = base(zeros++, 0); // zeros on the right hand side
                digit carry = 0;
                for(base::reverse_iterator j = rhs.digits.rbegin(); j != rhs.digits.rend(); j++){
                    double_digit prod = (double_digit(*i) * double_digit(*j)) + carry;// multiply through
                    row.digits.push_front(prod & NEG1);
                    carry = prod >> BITS;
                }
                if (carry)
                    row.digits.push_front(carry);
                out = add(out, row);
            }
            return out;
        }
typedef uint32位;//原始代码使用uint8_t;uint16\t也能工作
typedef uint64\u t两位数;//用于保存溢出值的int类型
typedef std::deque base;
常量数字NEG1=-1;//uint8\u t->255,uint32\u t->4294967295
常量数字位=sizeof(数字)>(uint64\u t移位){
如果(移位>=位())
返回整数(0);
基数=位数;
对于(uint64_t i=0;i<(移位/位);i++)
out.pop_back();
移位%=位;
如果(班次){
碱基v;
对于(d_size i=out.size()-1;i!=0;i--)
v、 向前推((向外[i]>>移位)|(向外[i-1]>移位);
out=v;
}
返回整数(out,_符号);
}
//接线员呼叫这个
整数相加(整数和左、整数和右){
基地建设;
base::reverse_迭代器i=lhs.digits.rbegin(),j=rhs.digits.rbegin();
布尔进位=假;
两位数和;
对于(;((i!=lhs.digits.rend())&&(j!=rhs.digits.rend());i++,j++){
总和=*i+*j+进位;
向外。向前推(总和);
进位=(和>负1);
}
对于(;i!=lhs.digits.rend();i++){
总和=*i+进位;
向外。向前推(总和);
进位=(和>负1);
}
对于(;j!=rhs.digits.rend();j++){
和=*j+进位;
向外。向前推(总和);
进位=(和>负1);
}
如果(携带)
向外。向前推(1);
返回整数(out);
}
//接线员打电话来
//长乘法
整数长×多(整数和左、整数和右){
无符号整数零=0;
整数行,out=0;
for(base::reverse_迭代器i=lhs.digits.rbegin();i!=lhs.digits.rend();i++){
row.digits=base(零++,0);//右侧的零
数字进位=0;
for(base::reverse_迭代器j=rhs.digits.rbegin();j!=rhs.digits.rend();j++){
双位数乘积=(双位数(*i)*双位数(*j))+进位;//相乘
行数字。向前推(prod&NEG1);
进位=生产>>位;
}
如果(携带)
行。数字。向前推(进位);
out=添加(out,row);
}
返回;
}
是否有一些明显的东西我错过了,可能会导致错误的计算?我已经盯着这段代码太久了

完整的修改代码是


编辑:我已经在上测试了代码,它返回了正确的计算值,但我的计算机仍然没有返回。对此有什么好的解释吗?

问题似乎是由于意外的过度右移。您提到您的ideone帖子没有重现该问题。在测试时,我没有我注意到在你的ideone帖子中,数字的类型实际上仍然设置为16位。当我将其更改为32位时(为了反映SO代码片段)尝试在gcc下编译时,我收到了一系列关于右移位过多的警告。运行该程序导致了一个无限循环,再加上右移位警告以及您在平台上获得不同行为的事实,强烈表明正在发生未定义的行为

更具体地说,在某些地方,int类型之间的位大小不匹配(即,您仍然有一些代码块需要更新)

问题制造者似乎是从Z开始设置的。这里有由Z指定的整数类型,以及由base::value_type指定的整数类型。这两个类型不能保证具有相同的位数,因此当发生位不匹配时,该函数中的位移位和位掩码代码无法正常工作。并且,seve也发生了不匹配当uint32_t是数字类型(至少在我的环境中)时,ideone代码中出现的该模板的ral实例化

编辑:根据标准:参考:,确认未定义过度右移,请参阅引用标准的已接受答案

(C++98§5.8/1)规定: 行为是 如果右操作数为负或大于或等于,则未定义 升级后的左操作数的位长度


你能只使用<代码> Boo::DycimixBITSET 还是<代码> STD::向量 -假设左边有一个重要的比特在它的开头?看起来问题是,运载不是发生在中间的溢出上。不确定原因是什么,但是它可能与移位有关。(并非所有环境都有一致的wrt位移位行为;MSVC喜欢叛逆)。您使用哪种编译器/平台?请注意,使用g++4.6.3(选项-std=gnu++0x)编译ideone代码在我的Ubuntu盒上也会产生123456789abcdf00fedcba987654321。我可以请你提供更多帮助吗?我更改了
setFromZ
,但是