Итак, я реализовал целый Unlimited Unsigned целочисленный класс, используя связанный список для проекта Euler, над которым я работаю. Я проверил, что все логические операции бит корректны (хотя я могу опубликовать их, если вы хотите их увидеть). Я уже реализовал все операторы и операции. Однако вычитание (и все его использование, т. Е. Деление и модуль) не работает. Когда я запускаю следующий тест, это то, что я получаю:Неограниченная реализация неподписанных целых целых связанных списков. Вычитание не работает
LimitlessUnsigned limitless = 0x88888888u;
limitless = limitless << 4;
LimitlessUnsigned tester = 0x88888884u;
tester = tester << 4;
//limitless = limitless >> 5;
LimitlessUnsigned another = limitless - tester;
я получаю следующие значения из отладчика:
another LimitlessUnsigned
integerList std::__1::list<unsigned int, std::__1::allocator<unsigned int> >
[0] unsigned int 0b11111111111111111111111111111111
[1] unsigned int 0b00000000000000000000000001000000
limitless LimitlessUnsigned
integerList std::__1::list<unsigned int, std::__1::allocator<unsigned int> >
[0] unsigned int 0b00000000000000000000000000001000
[1] unsigned int 0b10001000100010001000100010000000
tester LimitlessUnsigned
integerList std::__1::list<unsigned int, std::__1::allocator<unsigned int> >
[0] unsigned int 0b00000000000000000000000000001000
[1] unsigned int 0b10001000100010001000100001000000
кажется, что я что-то пропустил с определением вычитания и два-х комплимент. Код работает, пока мне не нужно добавить дополнительные 32 бита. Я учитываю переполнение, начиная с первых 32 до следующего 32. Однако я отказываюсь от переполнения на самом высоком бите (как я и думал). Очевидно, что я делаю это неправильно. Ниже приведен соответствующий исходный код.
void LimitlessUnsigned::Sub(const LimitlessUnsigned& other)
{
if(*this <= other)
{
*this = 0u;
return;
}
LimitlessUnsigned temp = other;
while(temp.integerList.size() > integerList.size())
integerList.push_front(0u);
while(integerList.size() > temp.integerList.size())
temp.integerList.push_front(0u);
temp.TwosComp();
Add(temp, true);
}
void LimitlessUnsigned::Add(const LimitlessUnsigned& other, bool allowRegisterLoss)
{
LimitlessUnsigned carry = *this & other;
LimitlessUnsigned result = *this^other;
while(carry != 0u)
{
carry.ShiftLeft(1, allowRegisterLoss);
LimitlessUnsigned shiftedcarry = carry;
carry = result & shiftedcarry;
result = result^shiftedcarry;
}
*this = result;
}
void LimitlessUnsigned::Not()
{
for(std::list<unsigned>::iterator iter = integerList.begin(); iter != integerList.end(); ++iter)
{
*iter = ~*iter;
}
}
void LimitlessUnsigned::TwosComp()
{
Not();
Add(1u, true);
}
void LimitlessUnsigned::ShiftLeft(unsigned shifts, bool allowRegisterLoss)
{
unsigned carry = 0u;
bool front_carry = false;
while(shifts > 0u)
{
if((integerList.front() & CARRY_INT_HIGH) == CARRY_INT_HIGH)
front_carry = true;
for(std::list<unsigned>::reverse_iterator iter = integerList.rbegin(); iter != integerList.rend(); ++iter)
{
unsigned temp = *iter;
*iter = *iter << 1;
*iter = *iter | carry;
if((temp & CARRY_INT_HIGH) == CARRY_INT_HIGH)
carry = CARRY_INT;
else
carry = 0u;
}
carry = 0u;
if(front_carry && !allowRegisterLoss)
{
front_carry = false;
integerList.push_front(1u);
}
--shifts;
}
}
Update я, наконец, решить эту проблему. Вот мой блог вместе с исходным кодом:
http://memmove.blogspot.com/2013/04/unlimited-unsigned-integer-in-c.html
Поскольку вы рассматриваете все как неподписанные, когда вы создаете дополнение двух, вы будете рассматривать его как огромное положительное число, а затем добавьте его вместо вычитания. – Barmar
@Barmar Ну, я смещаю биты от низких членов списка до высоких членов, пока не ударяю фронт(). Тогда я позволил этому упасть. Я не рассматриваю его как огромное положительное число? Если вы посмотрите на трассировку, элемент нижнего списка будет правильным в разнице. –
Выполнение беззнакового вычитания, добавляя дополнение двух, работает только с модульной арифметикой. С бесконечной точностью арифметики вы просто продолжаете добавлять и никогда не обматывать. – Barmar