Binary logic emulator logic error - c++

If you need any more information just ask.
What I'm trying to do is emulate boolean logic that could be found on a computer in C++ code. Right now I'm trying to create a 32 bit adder. When I run the testing code, I get an output of 32, which is wrong it should be 64. I'm fairly sure that my add function is correct. The code for those gates is:
bool and(bool a, bool b)
{
return nand(nand(a,b),nand(a,b));
}
bool or(bool a, bool b)
{
return nand(nand(a,a),nand(b,b));
}
bool nor(bool a, bool b)
{
return nand(nand(nand(a,a), nand(b,b)),nand(nand(a,a), nand(b,b)));
}
The code for the add function:
bool *add(bool a, bool b, bool carry)
{
static bool out[2];
out[0] = nor(nor(a, b), carry);
out[1] = or(and(b,carry),and(a,b));
return out;
}
bool *add32(bool a[32], bool b[32], bool carry)
{
static bool out[33];
bool *tout;
for(int i = 0; i < 32; i++)
{
tout = add(a[i], b[i], (i==0)?false:tout[1]);
out[i] = tout[0];
}
out[32] = tout[1];
return out;
}
The code I'm using to test this is:
bool *a = int32tobinary(32);
bool *b = int32tobinary(32);
bool *c = add32(a, b, false);
__int32 i = binarytoint32(c);
Those two functions are:
bool *int32tobinary(__int32 a)
{
static bool _out[32];
bool *out = _out;
int i;
for(i = 31; i >= 0; i--)
{
out[i] = (a&1) ? true : false;
a >>= 1;
}
return out;
}
__int32 binarytoint32(bool b[32])
{
int result = 0;
int i;
for(i = 0; i < 32; i++)
{
if(b[i] == true)
result += (int)pow(2.0f, 32 - i - 1);
}
return result;
}

Where to start?
As noted in the comments, returning a pointer to a static variable is wrong.
This
out[0] = nor(nor(a, b), carry);
should be
out[0] = xor(xor(a, b), carry);
This out[1] = or(and(b,carry),and(a,b)); is also incorrect. out[1] must be true, when a == true and carry == true.
add32 assumes index 0 to be the LSB, int32tobinary and int32tobinary assume index 0 to be MSB.

Related

Purpose of custom BitSet implementation in this Leetcode answer

Last night I was working on the "Longest Palindromic Subsequence" problem on leetcode. After completing it I took a look at the fastest answer, and to my surprise it was a giant custom bitset implementation. I decided to try and reverse engineer it a bit and see if I could implement it using std::bitset, but I've run into some issues.
Here's the code:
#if __cplusplus>199711L //c++11
#include<unordered_map>
#endif
const int N=1005;
template<int S>
struct BitSet{
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
typedef unsigned long long uint; //typedef unsigned int uint;
uint a[get_size(S)];int size;
void reset(){memset(a,0,sizeof(uint)*size);}
BitSet():size(get_size(S)){reset();}
BitSet(uint x):size(get_size(S)){reset();a[0]=x;}
BitSet(const BitSet<S> &x):size(get_size(S)){*this=x;}
BitSet& set(int x,int y){
//if (y<0||y>1){printf("error!\n");return *this;}
int X=x>>W,Y=x&mask;
if (y)a[X]|=1ull<<Y;else a[X]&=~(1ull<<Y);
return *this;
}
int find(int x){int X=x>>W,Y=x&mask;return (a[X]>>Y)&1ull;}
int operator [](int x){return find(x);}
BitSet& operator =(const BitSet &y){
memcpy(a,y.a,sizeof(uint)*size);
return *this;
}
BitSet<S> operator |(const BitSet<S> &y)const{return BitSet<S>(*this)|=y;}
BitSet<S> operator &(const BitSet<S> &y)const{return BitSet<S>(*this)&=y;}
BitSet<S> operator ^(const BitSet<S> &y)const{return BitSet<S>(*this)^=y;}
BitSet<S> operator +(const BitSet<S> &y)const{return BitSet<S>(*this)+=y;}
BitSet<S> operator -(const BitSet<S> &y)const{return BitSet<S>(*this)-=y;}
BitSet<S> operator <<(int x)const{return BitSet<S>(*this)<<=x;}
BitSet<S> operator >>(int x)const{return BitSet<S>(*this)>>=x;}
BitSet<S> operator ~()const{return BitSet<S>(*this).flip();}
BitSet<S>& operator =(const char *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!='0'&&s[i]!='1')break;
int X=i>>W,Y=i&mask;
if (s[i]=='1')a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator =(const int *s){
memset(a,0,sizeof(uint)*size);
for (int i=0;i<S;++i){
if (s[i]!=0&&s[i]!=1)break;
int X=i>>W,Y=i&mask;
if (s[i]==1)a[X]|=1ull<<Y;
}
return *this;
}
BitSet<S>& operator <<=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
if (delta==0)for (uint *p=a+size-1,*q=p-shift,*end=a+shift-1;p!=end;--p,--q)*p=*q;
else {
for (uint *p=a+size-1,*q1=p-shift,*q2=p-shift-1,*end=a+shift;p!=end;--p,--q1,--q2)*p=(*q1<<delta)|(*q2>>delta1);
a[shift]=a[0]<<delta;
}
memset(a,0,sizeof(uint)*shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0;
return *this;
}
BitSet<S>& operator >>=(int x){
int shift=x>>W; int delta=x&mask,delta1=mask+1-delta;
if (!x)return *this;
correction();
if (delta==0)for (uint *p=a,*q=p+shift,*end=a+size-shift;p!=end;++p,++q)*p=*q;
else {
for (uint *p=a,*q1=p+shift,*q2=p+shift+1,*end=a+size-shift-1;p!=end;++p,++q1,++q2)*p=(*q1>>delta)|(*q2<<delta1);
a[size-shift-1]=a[size-1]>>delta;
}
memset(a+size-shift,0,sizeof(uint)*shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA|=*startB;++startA;++startB;}
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA&=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator ^=(const BitSet<S> &y){
uint *startA=a;const uint *startB=y.a,*endA=a+size;
while (startA!=endA){*startA^=*startB;++startA;++startB;}
return *this;
}
BitSet<S>& operator +=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1+*q+t;
t=(*p<p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S> &y){
uint t=0,*p=a,*end=a+size; const uint *q=y.a;
while (p!=end){
uint p1=*p; *p=p1-*q-t;
t=(*p>p1)||(p1+t<t);
++p; ++q;
}
return *this;
}
operator bool(){return count()>0;}
BitSet<S>& flip(){
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0=~*p0; p0+=4;
*p1=~*p1; p1+=4;
*p2=~*p2; p2+=4;
*p3=~*p3; p3+=4;
}
for (int i=0;i<(size&3);++i,++p0)*p0=~*p0;
return *this;
}
//void flip(){*this=~*this;}
void flip(int x){a[x>>W]^=1ull<<(x&mask);}
int popcount(uint x)const{
x-=(x&0xaaaaaaaaaaaaaaaaull)>>1;
x=((x&0xccccccccccccccccull)>>2)+(x&0x3333333333333333ull);
x=((x>>4)+x)&0x0f0f0f0f0f0f0f0full;
return (x*0x0101010101010101ull)>>56;
}
int count(){
int res=0;
correction();
for (int i=0;i<size;++i)res+=__builtin_popcountll(a[i]); //popcount
return res;
}
int clz(){
correction();
int res=0;
if (a[size-1])res=__builtin_clzll(a[size-1])-(mask+1-(S&mask));
else {
res+=S&mask;
for (int i=size-2;i>=0;--i)
if (a[i]){res+=__builtin_clzll(a[i]); break;}
else res+=mask+1;
}
return res;
}
int ctz(){
correction();
int res=0;
for (int i=0;i<size;++i)
if (a[i]){res+=__builtin_ctzll(a[i]); break;}
else res+=mask+1;
return min(res,S);
}
int ffs(){
int res=ctz()+1;
if (res==S+1)res=0;
return res;
}
uint to_uint(){
correction();
return a[0];
}
void print(){
for (int i=0;i<size;++i)
for (int j=0;j<=mask&&(i<<W)+j+1<=S;++j)printf("%I64d",(a[i]>>j)&1ull);
printf("\n");
}
void correction(){if (S&mask)a[size-1]&=(1ull<<(S&mask))-1;}
#undef mask
#undef W
#undef get_size
};
int a[N],b[N];
BitSet<N> row[2],X,Y;
unordered_map<int,vector<int> > S;
unordered_map<int,BitSet<N> > match;
class Solution {
public:
int longestPalindromeSubseq(string s) {
int n=s.size(),m=n;
S.clear();match.clear();row[1].reset();
for (int i=0;i<n;++i)a[i]=int(s[i]),S[a[i]].push_back(i);
for (int i=0;i<m;++i)b[i]=int(s[n-1-i]);
for (int i=0;i<m;++i)if (match.find(b[i])==match.end()){
unordered_map<int,BitSet<N> >::iterator x=match.insert(make_pair(b[i],BitSet<N>())).first;
for (vector<int>::iterator j=S[b[i]].begin();j!=S[b[i]].end();++j)x->second.set(*j,1);
}
for (int i=0,now=0;i<m;++i,now^=1)
X=(row[now^1]|match[b[i]]).set(n,1),row[now]=(X&((X-(row[now^1]<<1).set(0,1))^X)).set(n,0);
return row[(m-1)&1].count();
}
};
And here's my attempt at cleaning it up/understanding it:
Bitset.h:
#pragma once
//#if __cplusplus>199711L //c++11
#include<unordered_map>
//#endif
#include <intrin.h>
const int N = 1005; //this size doesn't even matter?? It's just enigmatically assigning a type of int, I guess??
template<int S>
struct BitSet {
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
//members
typedef unsigned long long uint; //typedef unsigned int uint; //not sure why they didn't just use size_t here...
uint a[get_size(S)]; //represents the "BitSet" I think...
int size;
//constructors
BitSet() :size(get_size(S)) { reset(); }
BitSet(uint x) :size(get_size(S)) { reset(); a[0] = x; }
BitSet(const BitSet<S>& x) :size(get_size(S)) { *this = x; }
//utility functions
BitSet& set(int x, int y) {
//if (y<0||y>1){printf("error!\n");return *this;}
int X = x >> W, Y = x & mask; //bit shift with the magic numbers??? //What is the significance of 6, 63, and 1005?
if (y)a[X] |= 1ull << Y; else a[X] &= ~(1ull << Y);
return *this;
}
void reset() { memset(a, 0, sizeof(uint) * size); }
int find(int x) { int X = x >> W, Y = x & mask; return (a[X] >> Y) & 1ull; }
//void flip(){*this=~*this;}
void flip(int x) { a[x >> W] ^= 1ull << (x & mask); }
int popcount(uint x)const {
x -= (x & 0xaaaaaaaaaaaaaaaaull) >> 1;
x = ((x & 0xccccccccccccccccull) >> 2) + (x & 0x3333333333333333ull);
x = ((x >> 4) + x) & 0x0f0f0f0f0f0f0f0full;
return (x * 0x0101010101010101ull) >> 56;
}
int count() {
int res = 0;
correction();
for (int i = 0; i < size; ++i)res += __popcnt(a[i]); //popcount // __builtin_popcountll is only available on GCC apparently. Substituted with library version.
return res;
}
int clz() {
correction();
int res = 0;
if (a[size - 1])res = __builtin_clzll(a[size - 1]) - (mask + 1 - (S & mask));
else {
res += S & mask;
for (int i = size - 2; i >= 0; --i)
if (a[i]) { res += __builtin_clzll(a[i]); break; }
else res += mask + 1;
}
return res;
}
int ctz() {
correction();
int res = 0;
for (int i = 0; i < size; ++i)
if (a[i]) { res += __builtin_ctzll(a[i]); break; }
else res += mask + 1;
return min(res, S);
}
int ffs() {
int res = ctz() + 1;
if (res == S + 1)res = 0;
return res;
}
uint to_uint() {
correction();
return a[0];
}
void print() {
for (int i = 0; i < size; ++i)
for (int j = 0; j <= mask && (i << W) + j + 1 <= S; ++j)printf("%I64d", (a[i] >> j) & 1ull);
printf("\n");
}
void correction() { if (S & mask)a[size - 1] &= (1ull << (S & mask)) - 1; }
BitSet<S>& flip() {
//for (uint *start=a,*end=a+size;start!=end;*start=~*start,++start);
uint* p0 = a, * p1 = p0 + 1, * p2 = p0 + 2, * p3 = p0 + 3, * pend = a + ((size >> 2) << 2);
while (p0 != pend) {
*p0 = ~*p0; p0 += 4;
*p1 = ~*p1; p1 += 4;
*p2 = ~*p2; p2 += 4;
*p3 = ~*p3; p3 += 4;
}
for (int i = 0; i < (size & 3); ++i, ++p0)*p0 = ~*p0;
return *this;
}
//operators
int operator [](int x) { return find(x); }
BitSet& operator =(const BitSet& y) {
memcpy(a, y.a, sizeof(uint) * size);
return *this;
}
BitSet<S>& operator =(const char* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != '0' && s[i] != '1')break;
int X = i >> W, Y = i & mask;
if (s[i] == '1')a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S>& operator =(const int* s) {
memset(a, 0, sizeof(uint) * size);
for (int i = 0; i < S; ++i) {
if (s[i] != 0 && s[i] != 1)break;
int X = i >> W, Y = i & mask;
if (s[i] == 1)a[X] |= 1ull << Y;
}
return *this;
}
BitSet<S> operator |(const BitSet<S>& y)const { return BitSet<S>(*this) |= y; }
BitSet<S> operator &(const BitSet<S>& y)const { return BitSet<S>(*this) &= y; }
BitSet<S> operator ^(const BitSet<S>& y)const { return BitSet<S>(*this) ^= y; }
BitSet<S> operator +(const BitSet<S>& y)const { return BitSet<S>(*this) += y; }
BitSet<S> operator -(const BitSet<S>& y)const { return BitSet<S>(*this) -= y; }
BitSet<S> operator <<(int x)const { return BitSet<S>(*this) <<= x; }
BitSet<S> operator >>(int x)const { return BitSet<S>(*this) >>= x; }
BitSet<S> operator ~()const { return BitSet<S>(*this).flip(); }
BitSet<S>& operator <<=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
if (delta == 0)for (uint* p = a + size - 1, *q = p - shift, *end = a + shift - 1; p != end; --p, --q)*p = *q;
else {
for (uint* p = a + size - 1, *q1 = p - shift, *q2 = p - shift - 1, *end = a + shift; p != end; --p, --q1, --q2)*p = (*q1 << delta) | (*q2 >> delta1);
a[shift] = a[0] << delta;
}
memset(a, 0, sizeof(uint) * shift); //for (uint *p=a,*end=a+shift;p!=end;++p)*p=0; //if this is a left shift... why is it setting the beginning of the "a" array to 0???... unless the damn array is "backwards". Sheesh.
//wait... this is a right shift according to https://orthallelous.wordpress.com/2019/10/24/magic-numbers-encoding-truth-tables-into-giant-single-values/ ... fuck.
return *this;
}
BitSet<S>& operator >>=(int x) {
int shift = x >> W; int delta = x & mask, delta1 = mask + 1 - delta;
if (!x)return *this;
correction();
if (delta == 0)for (uint* p = a, *q = p + shift, *end = a + size - shift; p != end; ++p, ++q)*p = *q;
else {
for (uint* p = a, *q1 = p + shift, *q2 = p + shift + 1, *end = a + size - shift - 1; p != end; ++p, ++q1, ++q2)*p = (*q1 >> delta) | (*q2 << delta1);
a[size - shift - 1] = a[size - 1] >> delta;
}
memset(a + size - shift, 0, sizeof(uint) * shift);
return *this;
}
BitSet<S>& operator |=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA |= *startB; ++startA; ++startB; }
//for (int i=0;i<size;++i)a[i]|=y.a[i];
return *this;
}
/*BitSet<S>& operator |=(const BitSet<S> &y){
uint *p0=a,*p1=p0+1,*p2=p0+2,*p3=p0+3;const uint *q0=y.a,*q1=q0+1,*q2=q0+2,*q3=q0+3,*pend=a+((size>>2)<<2);
while (p0!=pend){
*p0|=*q0; p0+=4; q0+=4;
*p1|=*q1; p1+=4; q1+=4;
*p2|=*q2; p2+=4; q2+=4;
*p3|=*q3; p3+=4; q3+=4;
}
for (int i=0;i<(size&3);++i)*p0++|=*q0++;
return *this;
}*/
BitSet<S>& operator &=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA &= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator ^=(const BitSet<S>& y) {
uint* startA = a; const uint* startB = y.a, * endA = a + size;
while (startA != endA) { *startA ^= *startB; ++startA; ++startB; }
return *this;
}
BitSet<S>& operator +=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
BitSet<S>& operator -=(const BitSet<S>& y) {
uint t = 0, * p = a, * end = a + size; const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
operator bool() { return count() > 0; }
#undef mask
#undef W
#undef get_size
};
LeetCode516.cpp
// LeetCode516.cpp : This file contains the 'main' function. Program execution begins and ends there.
//
#include <iostream>
#include "BitSet.h"
#include <bitset>
// If parameter is not true, test fails
// This check function would be provided by the test framework
#define IS_TRUE(x) { if (!x) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; else std::cout << __FUNCTION__ << " passed" << std:: endl;}
int longestPalindromeSubseq(std::string s) {
int a[N] = { 0 }, b[N] = { 0 }; //2 integer arrays - initialzing to 0 isn't necessary, but seems to make the debug output more readable?
BitSet<N> row[2], X, Y; //3 bitsets... one of them is actually 2 (lol)
std::unordered_map<int, std::vector<int>> S; //This map tracks the number of occurrences of each letter?
std::unordered_map<int, BitSet<N>> match;
int n = s.size(), m = n;
S.clear();
match.clear();
//row[1].reset(); //WTF is this? Garbage.
//For each piece of the string, cast it from a char to an int and shove it in the first array, then push back a copy of each array into the UOMap S.
for (int i = 0; i < n; ++i) {
a[i] = static_cast<int>(s[i]); //changed C-style cast to static_cast
S[a[i]].push_back(i);
}
//Set the second array to a backwards copy of A I guess? (while converting the characters to integers ofc)
for (int i = 0; i < m; ++i) {
b[i] = int(s[n - 1 - i]);
}
for (int i = 0; i < m; ++i) {
//so if it's the first loop iteration or the find (working on the "backwards" array) matches the end, do this:
if (match.find(b[i]) == match.end()) { //how does this even run the first time? Match is getting cleared and never set? I guess it's working because "find(b[i])" and "end()" are both 0? - Kind of - turns out that if the find function fails, it returns "end"...
//Insert a new bitset with a "key" of "b[i]" into the match map.
auto x = match.insert(std::make_pair(b[i], BitSet<N>())).first; // replaced std::unordered_map<int, BitSet<N> >::iterator with auto... that's nice.
//Then using the iterator we just created above, loop through all entries in UOMap S under that key and ???
//Since we found it in "match", lets check for it(?) in UOMap S... and then set some bit in match based on how many entries there are in S?
for (auto j = S[b[i]].begin(); j != S[b[i]].end(); ++j) {
x->second.set(*j, 1); //this is setting some bit value in "match" to 1 I guess.
}
}
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1) { //Is "*=" being intentionally obfuscated here to "^=" or is it actually different?? Ugh... nasty.
X = (row[now ^ 1] | match[b[i]]).set(n, 1); // if the caret is supposed to represent XOR, why does this still work whenever I replace it with a *... very funky.
row[now] = (X & ((X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
}
return row[(m - 1) & 1].count();
}
template<int S>
std::bitset<S>& operator-(const std::bitset<S>&y) { return std::bitset<S>(*this) -= y; }
#define W 6
#define mask 63
#define get_size(n) ((n)<1?0:((n)+mask)>>W)
template<size_t S>
std::bitset<S>& operator-(std::bitset<S>& y, const std::bitset<S>& z) {
//return std::bitset<S>(*this) -= y;
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0]; //z.a
while (p != end) {
size_t p1 = *p;
*p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator+(std::bitset<S>& y, const std::bitset<S>& z) {
size_t thing[get_size(S)];
size_t t = 0, * p = thing, * end = thing + get_size(y);
const size_t* q = z[0];
while (p != end) {
size_t p1 = *p; *p = p1 + *q + t;
t = (*p < p1) || (p1 + t < t);
++p;
++q;
}
return y;
}
template<size_t S>
std::bitset<S>& operator -=(const std::bitset<S>& y) {
uint t = 0, * p = a, * end = a + size;
const uint* q = y.a;
while (p != end) {
uint p1 = *p; *p = p1 - *q - t;
t = (*p > p1) || (p1 + t < t);
++p; ++q;
}
return *this;
}
int LPS_STL(std::string s) {
const int M = 1005;
int c[M], d[M];
std::bitset<M> row[2], X, Y;
std::unordered_map<int, std::vector<int> > S;
std::unordered_map<int, std::bitset<M> > match;
int n = s.size(), m = n;
S.clear();
match.clear();
row[1].reset();
for (int i = 0; i < n; ++i)c[i] = int(s[i]), S[c[i]].push_back(i);
for (int i = 0; i < m; ++i)d[i] = int(s[n - 1 - i]);
for (int i = 0; i < m; ++i)if (match.find(d[i]) == match.end()) {
std::unordered_map<int, std::bitset<M> >::iterator x = match.insert(std::make_pair(d[i], std::bitset<M>())).first;
for (std::vector<int>::iterator j = S[d[i]].begin(); j != S[d[i]].end(); ++j)x->second.set(*j, 1);
}
for (int i = 0, now = 0; i < m; ++i, now ^= 1)
X = (row[now ^ 1] | match[d[i]]).set(n, 1), row[now] = (X & (( X - (row[now ^ 1] << 1).set(0, 1)) ^ X)).set(n, 0);
return row[(m - 1) & 1].count();
}
void test1() {
int test = longestPalindromeSubseq("");
IS_TRUE(test == 0);
}
void test2() {
int test = longestPalindromeSubseq("bbbab");
IS_TRUE(test == 4);
}
void test3() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 2);
}
void test4() {
int test = longestPalindromeSubseq("cbbd");
IS_TRUE(test == 0); //purposefully fail
}
void test5() {
int test = longestPalindromeSubseq("cacbcbba");
IS_TRUE(test == 5);
}
void test6() {
int test = longestPalindromeSubseq("eeeecdeabfbeeb");
IS_TRUE(test == 7);
}
//Std::bitset tests
//void test7() {
// int test = LPS_STL("");
// IS_TRUE(test == 0);
//}
//void test8() {
// int test = LPS_STL("bbbab")
// IS_TRUE(test == 4);
//}
int main()
{
std::cout << "Longest Palindrome Subsequence\n";
test1();
test2();
test3();
test4();
test5();
test6();
test7();
test8();
}
Main question: Is there a core reason this person chose to implement a custom bitset instead of the std library?
Extraneous questions:
Is some of this code intentionally obfuscated?
It feels a bit naive to ask this, but do some of you intentionally code this way?
Why are they using the value of N (an int) as the type for their bitsets?
Some of their formulas are incredibly long.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Is this question more appropriate for another SO site, such as Code Review?
Is some of this code intentionally obfuscated?
It is just faster to type
#define W 6
than
constexpr size_t bitcoverage { std::bitwidth(sizeof(int64_t)*CHAR_BIT)-1 }; // bits needed to represent 8*8=64 2^7 so 7-1=6 which 0-63 bits.
(if I got it right ...)
It feels a bit naive to ask this, but do some of you intentionally code this way?
When I started programming I did, now I have realized that code is read more than written and it could confuse people, including me, who read it later.
Why are they using the value of N (an int) as the type for their bitsets?
N is just how many entries there is max, see the link you provided.
It actually uses an int64_t to store the bits. Which for many operaton on most larger CPU's is far more efficient than the same doing the same operation on an byte as you can do or/and/etc on a lot of bits with just one instuction.
Some of their formulas are incredibly long.
I am not sure which your are speculating about.
Attempting to implement the necessary operators for the std::bitset implementation didn't go well. Can someone elucidate the reason these don't exist? I feel like there's a good reason for it regarding expected output, but I can't articulate it.
Again, what exact are you referring to?

Adding negative and positive numbers up to 10^100000

I've been trying to solve this problem (from school) for just about a week now. We're given two numbers, from -(10^100000) to +that.
Of course the simplest solution is to implement written addition, so that's what I did. I decided, that I would store the numbers as strings, using two functions:
int ti(char a) { // changes char to int
int output = a - 48;
return output;
}
char tc(int a) { // changes int to char
char output = a + 48;
return output;
}
This way I can store negative digits, like -2. With that in mind I implemented a toMinus function:
void toMinus(std::string &a) { // 123 -> -1 -2 -3
for (auto &x : a) {
x = tc(-ti(x));
}
}
I also created a changeSize function, which adds 0 to the beginning of the number until they are both their max size + 1 and removeZeros, which removes leading zeros:
void changeSize(std::string &a, std::string &b) {
size_t exp_size = std::max(a.size(), b.size()) + 2;
while (a.size() != exp_size) {
a = '0' + a;
}
while (b.size() != exp_size) {
b = '0' + b;
}
}
void removeZeros(std::string &a) {
int i = 0;
for (; i < a.size(); i++) {
if (a[i] != '0') {
break;
}
}
a.erase(0, i);
if (a.size() == 0) {
a = "0";
}
}
After all that, I created the main add() function:
std::string add(std::string &a, std::string &b) {
bool neg[2] = {false, false};
bool out_negative = false;
if (a[0] == '-') {
neg[0] = true;
a.erase(0, 1);
}
if (b[0] == '-') {
neg[1] = true;
b.erase(0, 1);
}
changeSize(a, b);
if (neg[0] && !(neg[1] && neg[0])) {
toMinus(a);
}
if(neg[1] && !(neg[1] && neg[0])) {
toMinus(b);
}
if (neg[1] && neg[0]) {
out_negative = true;
}
// Addition
for (int i = a.size() - 1; i > 0; i--) {
int _a = ti(a[i]);
int _b = ti(b[i]);
int out = _a + _b;
if (out >= 10) {
a[i - 1] += out / 10;
} else if (out < 0) {
if (abs(out) < 10) {
a[i - 1]--;
} else {
a[i - 1] += abs(out) / 10;
}
if (i != 1)
out += 10;
}
a[i] = tc(abs(out % 10));
}
if (ti(a[0]) == -1) { // Overflow
out_negative = true;
a[0] = '0';
a[1]--;
for (int i = 2; i < a.size(); i++) {
if (i == a.size() - 1) {
a[i] = tc(10 - ti(a[i]));
} else {
a[i] = tc(9 - ti(a[i]));
}
}
}
if (neg[0] && neg[1]) {
out_negative = true;
}
removeZeros(a);
if (out_negative) {
a = '-' + a;
}
return a;
}
This program works in most cases, although our school checker found that it doesn't - like instead of
-4400547114413430129608370706728634555709161366260921095898099024156859909714382493551072616612065064
it returned
-4400547114413430129608370706728634555709161366260921095698099024156859909714382493551072616612065064
I can't find what the problem is. Please help and thank you in advance.
Full code on pastebin
While I think your overall approach is totally reasonable for this problem, your implementation seems a bit too complicated. Trying to solve this myself, I came up with this:
#include <iostream>
#include <limits>
#include <random>
#include <string>
bool greater(const std::string& a, const std::string& b)
{
if (a.length() == b.length()) return a > b;
return a.length() > b.length();
}
std::string add(std::string a, std::string b)
{
std::string out;
bool aNeg = a[0] == '-';
if (aNeg) a.erase(0, 1);
bool bNeg = b[0] == '-';
if (bNeg) b.erase(0, 1);
bool resNeg = aNeg && bNeg;
if (aNeg ^ bNeg && (aNeg && greater(a, b) || bNeg && greater(b, a)))
{
resNeg = true;
std::swap(a, b);
}
int i = a.length() - 1;
int j = b.length() - 1;
int carry = 0;
while (i >= 0 || j >= 0)
{
const int digitA = (i >= 0) ? a[i] - '0' : 0;
const int digitB = (j >= 0) ? b[j] - '0' : 0;
const int sum = (aNeg == bNeg ? digitA + digitB : (bNeg ? digitA - digitB : digitB - digitA)) + carry;
carry = 0;
if (sum >= 10) carry = 1;
else if (sum < 0) carry = -1;
out = std::to_string((sum + 20) % 10) + out;
i--;
j--;
}
if (carry) out = '1' + out;
while (out[0] == '0') out.erase(0, 1);
if (resNeg) out = '-' + out;
return out;
}
void test()
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(-std::numeric_limits<int32_t>::max(), std::numeric_limits<int32_t>::max());
for (int i = 0; i < 1000000; ++i)
{
const int64_t a = dis(gen);
const int64_t b = dis(gen);
const auto expected = std::to_string(a + b);
const auto actual = add(std::to_string(a), std::to_string(b));
if (actual != expected) {
std::cout << "mismatch expected: " << expected << std::endl;
std::cout << "mismatch actual : " << actual << std::endl;
std::cout << " a: " << a << std::endl;
std::cout << " b: " << b << std::endl;
}
}
}
int main()
{
test();
}
It can potentially be further optimized, but the main points are:
If the sign of both numbers is the same, we can do simple written addition. If both are negative, we simply prepend - at the end.
If the signs are different, we do written subtraction. If the minuend is greater than the subtrahend, there's no issue, we know that the result will be positive. If, however, the subtrahend is greater, we have to reformulate the problem. For example, 123 - 234 we would formulate as -(234 - 123). The inner part we can solve using regular written subtraction, after which we prepend -.
I test this with random numbers for which we can calculate the correct result using regular integer arithmetic. Since it doesn't fail for those, I'm pretty confident it also works correctly for larger inputs. An approach like this could also help you uncover cases where your implementation fails.
Other than that, I think you should use a known failing case with a debugger or simply print statements for the intermediate steps to see where it fails. The only small differences in the failing example you posted could point at some issue with handling a carry-over.

Issue with implementing "Closest pair of points" in C++

I'm trying to implement Closest pair of points in C++ according to Cormen book and wikipedia article, I think that algorithm is correct, but it does work only for a very small data. Code is below:
#include <cstdio>
#include <algorithm>
#include <cmath>
#define REP(i,n) for(int i=0;i<n;i++)
using namespace std;
struct point
{
long long x, y;
};
struct dist
{
long long x_1,y_1,x_2,y_2, distance;
} dis;
inline bool OrdX(const point &a, const point &b)
{
if(a.x==b.x)
{
return a.y<b.y;
}
return a.x<b.x;
}
inline int OrdY(const point &a, const point &b)
{
if(a.y==b.y)
{
return a.x<b.x;
}
return a.y<b.y;
}
// is - function that check is a an element of X_L array
inline bool is(const point &a, point *X_L, int p, int k)
{
if(p<=k)
{
int center = (p+k)/2;
if(X_L[center].x == a.x)
{
return true;
}
if(X_L[center].x > a.x)
{
return is(a, X_L, p, center-1);
}
else
{
return is(a, X_L, center+1, k);
}
}
return false;
}
// odl - function takes two points and return distance between them ^2
inline long long odl(const point &a, const point &b)
{
return ((a.x-b.x)*(a.x-b.x))+((a.y-b.y)*(a.y-b.y));
}
int tmp;
// fun - function that returns the pair of closest points using divide & conquer
struct dist fun(int n, point *X, point *Y)
{
// if there are less that 4 points - it checks it using bruteforce
if(n<4)
{
if(odl(X[0], X[1]) < dis.distance)
{
dis.distance = odl(X[0],X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
}
if(n==3)
{
if(odl(X[0], X[2]) < dis.distance)
{
dis.distance = odl(X[0],X[2]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[2].x;
dis.y_2 = X[2].y;
}
if(odl(X[1], X[2]) < dis.distance)
{
dis.distance = odl(X[1],X[2]);
dis.x_1 = X[1].x;
dis.y_1 = X[1].y;
dis.x_2 = X[2].x;
dis.y_2 = X[2].y;
}
}
}
// otherwise it divides points into two arrays and runs fun
// recursively foreach part
else
{
int p=n/2;
int PPP = (X[p].x + X[p-1].x)/2;
point *X_L = new point[p];
point *X_R = new point[n-p];
point *Y_L = new point[p];
point *Y_R = new point[n-p];
REP(i,p)
X_L[i] = X[i];
for(int r=p; r<n; r++)
{
X_R[r-p] = X[r];
}
int length_Y_L = 0;
int length_Y_R = 0;
REP(i,n)
{
if(is(Y[i], X_L, 0, p))
{
Y_L[length_Y_L++] = Y[i];
}
else
{
Y_R[length_Y_R++] = Y[i];
}
}
dist D_L = fun(p, X_L, Y_L);
dist D_R = fun(n-p, X_R, Y_R);
dist D;
if(D_L.distance < D_R.distance)
{
D = D_L;
}
else
{
D = D_R;
}
tmp = 0;
point *Y2 = new point[n];
double from = sqrt((double)D.distance);
for(int r=0; r<n; r++)
{
if(Y[r].x > (long long)PPP-from && Y[r].x < (long long)PPP + from)
{
Y2[tmp++] = Y[r];
}
}
//--tmp;
//int xxx = min(7, tmp-r);
int r = 0;
for(int j=1; j<min(7, tmp-r); j++)
{
if(odl(Y2[r], Y2[r+j]) < D.distance)
{
D.distance = odl(Y2[r], Y2[r+j]);
D.x_1 = Y2[r].x;
D.y_1 = Y2[r].y;
D.x_2 = Y2[r+j].x;
D.y_2 = Y2[r+j].y;
}
r++;
}
dis = D;
}
return dis;
}
int main()
{
int n;
n = 7;
point *X = new point[n];
point *Y = new point[n];
for(int i=0; i< 7; i++)
{
X[i].x = 0;
X[i].y = 10*i;
}
/*
REP(i,n)
{
scanf("%lld %lld", &X[i].x, &X[i].y);
}
*/
sort(X, X+n, OrdX);
REP(i,n)
Y[i] = X[i];
sort(Y, Y+n, OrdY);
dis.distance = odl(X[0], X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
dist wynik = fun(n, X, Y);
printf(" %lld %lld\n %lld %lld\n", wynik.x_1, wynik.y_1, wynik.x_2, wynik.y_2);
return 0;
}
and I get this error:
malloc.c:3096: sYSMALLOc: Assertion `(old_top == (((mbinptr) (((char
*) &((av)->bins[((1) - 1) * 2])) - __builtin_offsetof (struct
malloc_chunk, fd)))) && old_size == 0) || ((unsigned long) (old_size)
>= (unsigned long)((((__builtin_offsetof (struct malloc_chunk,
fd_nextsize))+((2 * (sizeof(size_t))) - 1)) & ~((2 * (sizeof(size_t)))
- 1))) && ((old_top)->size & 0x1) && ((unsigned long)old_end &
pagemask) == 0)' failed.
I've tried loooking for explanation of this error but can't find anything clear for me :/.
Can You please help me to solve this ? Thanks
The message means you've done something bad with dynamically allocated memory. Perhaps you freed an object twice, or wrote into memory beyond the beginning or end of an array-like dynamically allocated object.
On Linux, the tool valgrind may help pin-point the first place in your program's execution where it made a boo-boo.
By the way, your macro:
#define REP(i,n) for(int i=0;i<n;i++)
is poorly defined. The substitution of n should be parenthesized, because n could be an expression which has the wrong precedence with respect to the < operator. For instance: REP(i, k < m ? z : w). You want:
#define REP(var,n) for(int var=0;var<(n);var++)
The var reminds the programmer that this argument is a variable name, and not an arbitrary expression.
Your function is is redundant; that's just std::binary_search. That would help a lot with #sbi's problem of readability.
There's also quite a bit of redundancy in blocks like
dis.distance = odl(X[0],X[1]);
dis.x_1 = X[0].x;
dis.y_1 = X[0].y;
dis.x_2 = X[1].x;
dis.y_2 = X[1].y;
You can write a simple function dist calcDist(point,point) for this. You should probably move all the point definitions and associated functions to a separate header "point.h", again to keep things readable.
As for the memory issue: first, the arrays X_L and X_R are not really necessary. They contain the same data as X, so you can make them pointers to &(X[0]) and &(X[p) respectively. Y_L and Y_R are shuffled versions, so you do need to the arrays to copy data to. However, if you allocate them with new[], you are responsible for cleanup with delete[]. It looks like you can just use a std::vector<point> Y_L instead. No need to do bookkeeping, vector does that for you. Just call Y_L.push_back(Y[i]).

Storing a Big Number in a Variable and Looping

How can i store a big number in a variable and use a for loop?
I have a very big number 75472202764752234070123900087933251 and i need to loop from 0 to this number!
Is it even possible to do this? how much time will it take to end?
EDIT: i am trying to solve a hard problem by brute force. its a combination problem.the bruteforcing cases may reach 470C450.
so i guess i should use a different algorithm...
This might take
0.23 x 10^23 years if C++ processed 100,000 loops per second :|
http://www.wolframalpha.com/input/?i=75472202764752234070123900087933251%2F%28100000*1*3600*24*365%29
It looks that this number fits into 128 bit. So you could use a modern system and a modern compiler that implements such numbers. This would e.g be the case for a 64bit linux system with gcc as a compiler. This has something like __uint128_t that you could use.
Obviously you can't use such a variable as a for-loop variable, others have give you the calculations. But you could use it to store some of your calculations.
Well, you would need an implementation that can handle at least a subset of the initialization, boolean, and arithmetic functions on very large integers. Something like: https://mattmccutchen.net/bigint/.
For something that would give a bit better performance than a general large integer math library, you could use specialized operations specifically to allow use of a large integer as a counter. For an example of this, see dewtell's updated answer to this question.
As for it being possible for you to loop from 0 to that number: well, yes, it is possible to write the code for it with one of the above solutions, but I think the answer is no, you personally will not be able to do it because you will not be alive to see it finish.
[edit: Yes, I would definitely recommend you find a different algorithm. :D]
If you need to loop a certain number of times, and that number is greater than 2^64, just use while(1) because your computer will break before it counts up to 2^64 anyway.
There's no need for a complete bignum package - if all you need is a loop counter, here's a simple byte counter that uses an array of bytes as a counter. It stops when the byte array wraps around to all zeros again. If you wanted to count to some other value than 2^(bytesUsed*CHAR_BITS), you could just compute the two's complement value of the negative of the number of iterations you wanted, and let it count up to 0, keeping in mind that bytes[0] is the low-order byte (or use the positive value and count down instead of up).
#include <stdio.h>
#define MAXBYTES 20
/* Simple byte counter - note it uses argc as # of bytes to use for convenience */
int main(int argc, char **argv) {
unsigned char bytes[MAXBYTES];
const int bytesUsed = argc < MAXBYTES? argc : MAXBYTES;
int i;
unsigned long counter = (unsigned long)-1; /* to give loop something to do */
for (i = 0; i < bytesUsed; i++) bytes[i] = 0; /* Initialize bytes */
do {
for (i = 0; i < bytesUsed && !++bytes[i]; i++) ; /* NULL BODY - this is the byte counter */
counter++;
} while (i < bytesUsed);
printf("With %d bytes used, final counter value = %lu\n", bytesUsed, counter);
}
Run times for the first 4 values (under Cygwin, on a Lenovo T61):
$ time ./bytecounter
With 1 bytes used, final counter value = 255
real 0m0.078s
user 0m0.031s
sys 0m0.046s
$ time ./bytecounter a
With 2 bytes used, final counter value = 65535
real 0m0.063s
user 0m0.031s
sys 0m0.031s
$ time ./bytecounter a a
With 3 bytes used, final counter value = 16777215
real 0m0.125s
user 0m0.015s
sys 0m0.046s
$ time ./bytecounter a a a
With 4 bytes used, final counter value = 4294967295
real 0m6.578s
user 0m0.015s
sys 0m0.047s
At this rate, five bytes should take around half an hour, and six bytes should take the better part of a week. Of course the counter value will be inaccurate for those - it's mostly just there to verify the number of iterations for the smaller byte values and give the loop something to do.
Edit: And here's the time for five bytes, around half an hour as I predicted:
$ time ./bytecounter a a a a
With 5 bytes used, final counter value = 4294967295
real 27m22.184s
user 0m0.015s
sys 0m0.062s
Ok, here's code to take an arbitrary decimal number passed as the first arg and count down from it to zero. I set it up to allow the counter to use different size elements (just change the typedef for COUNTER_BASE), but it turns out that bytes are actually somewhat faster than either short or long on my system.
#include <stdio.h>
#include <limits.h> // defines CHAR_BIT
#include <ctype.h>
#include <vector>
using std::vector;
typedef unsigned char COUNTER_BASE;
typedef vector<COUNTER_BASE> COUNTER;
typedef vector<unsigned char> BYTEVEC;
const unsigned long byteMask = (~0ul) << CHAR_BIT;
const size_t MAXBYTES=20;
void mult10(BYTEVEC &val) {
// Multiply value by 10
unsigned int carry = 0;
int i;
for (i = 0; i < val.size(); i++) {
unsigned long value = val[i]*10ul+carry;
carry = (value & byteMask) >> CHAR_BIT;
val[i] = value & ~byteMask;
}
if (carry > 0) val.push_back(carry);
}
void addDigit(BYTEVEC &val, const char digit) {
// Add digit to the number in BYTEVEC.
unsigned int carry = digit - '0'; // Assumes ASCII char set
int i;
for (i = 0; i < val.size() && carry; i++) {
unsigned long value = static_cast<unsigned long>(val[i])+carry;
carry = (value & byteMask) >> CHAR_BIT;
val[i] = value & ~byteMask;
}
if (carry > 0) val.push_back(carry);
}
BYTEVEC Cstr2Bytevec(const char *str) {
// Turn a C-style string into a BYTEVEC. Only the digits in str apply,
// so that one can use commas, underscores, or other non-digits to separate
// digit groups.
BYTEVEC result;
result.reserve(MAXBYTES);
result[0]=0;
unsigned char *res=&result[0]; // For debugging
while (*str) {
if (isdigit(static_cast<int>(*str))) {
mult10(result);
addDigit(result, *str);
}
str++;
}
return result;
}
void packCounter(COUNTER &ctr, const BYTEVEC &val) {
// Pack the bytes from val into the (possibly larger) datatype of COUNTER
int i;
ctr.erase(ctr.begin(), ctr.end());
COUNTER_BASE value = 0;
for (i = 0; i < val.size(); i++) {
int pos = i%sizeof(COUNTER_BASE); // position of this byte in the value
if (i > 0 && pos == 0) {
ctr.push_back(value);
value = val[i];
} else {
value |= static_cast<COUNTER_BASE>(val[i]) << pos*CHAR_BIT;
}
}
ctr.push_back(value);
}
inline bool decrementAndTest(COUNTER &ctr) {
// decrement value in ctr and return true if old value was not all zeros
int i;
for (i = 0; i < ctr.size() && !(ctr[i]--); i++) ; // EMPTY BODY
return i < ctr.size();
}
inline bool decrementAndTest2(COUNTER_BASE *ctr, const size_t size) {
// decrement value in ctr and return true if old value was not all zeros
int i;
for (i = 0; i < size && !(ctr[i]--); i++) ; // EMPTY BODY
return i < size;
}
/* Vector counter - uses first arg (if supplied) as the count */
int main(int argc, const char *argv[]) {
BYTEVEC limit = Cstr2Bytevec(argc > 1? argv[1] : "0");
COUNTER ctr;
packCounter(ctr, limit);
COUNTER_BASE *ctr_vals = ctr.size() > 0 ? &ctr[0] : NULL;
size_t ctr_size = ctr.size();
unsigned long ul_counter = 0ul; /* to give loop something to do */
while(decrementAndTest2(ctr_vals, ctr_size)) {
ul_counter++;
};
printf("With %d bytes used, final ul_counter value = %lu\n", limit.size(), ul_counter);
return 0;
}
Examples of use:
$ time ./bigcounter 5
With 1 bytes used, final ul_counter value = 5
real 0m0.094s
user 0m0.031s
sys 0m0.047s
$ time ./bigcounter 5,000
With 2 bytes used, final ul_counter value = 5000
real 0m0.062s
user 0m0.015s
sys 0m0.062s
$ time ./bigcounter 5,000,000
With 3 bytes used, final ul_counter value = 5000000
real 0m0.093s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 1,000,000,000
With 4 bytes used, final ul_counter value = 1000000000
real 0m2.688s
user 0m0.015s
sys 0m0.015s
$ time ./bigcounter 2,000,000,000
With 4 bytes used, final ul_counter value = 2000000000
real 0m5.125s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 3,000,000,000
With 4 bytes used, final ul_counter value = 3000000000
real 0m7.485s
user 0m0.031s
sys 0m0.047s
$ time ./bigcounter 4,000,000,000
With 4 bytes used, final ul_counter value = 4000000000
real 0m9.875s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 5,000,000,000
With 5 bytes used, final ul_counter value = 705032704
real 0m12.594s
user 0m0.046s
sys 0m0.015s
$ time ./bigcounter 6,000,000,000
With 5 bytes used, final ul_counter value = 1705032704
real 0m14.813s
user 0m0.015s
sys 0m0.062s
Unwrapping the counter vector into C-style data structures (i.e., using decrementAndTest2 instead of decrementAndTest) sped things up by around 20-25%, but the code is still about twice as slow as my previous C program for similar-sized examples (around 4 billion). This is with MS Visual C++ 6.0 as the compiler in release mode, optimizing for speed, on a 2GHz dual-core system, for both programs. Inlining the decrementAndTest2 function definitely makes a big difference (around 12 sec. vs. 30 for the 5 billion loop), but I'll have to see whether physically inlining the code as I did in the C program can get similar performance.
the variable in main function can Store even 100 factorial
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <stack>
#include <queue>
#include <deque>
#include <limits>
#include <cmath>
#include <numeric>
#include <set>
using namespace std;
//template for BIGINIT
// base and base_digits must be consistent
const int base = 10;
const int base_digits = 1;
struct bigint {
vector<int> a;
int sign;
bigint() :
sign(1) {
}
bigint(long long v) {
*this = v;
}
bigint(const string &s) {
read(s);
}
void operator=(const bigint &v) {
sign = v.sign;
a = v.a;
}
void operator=(long long v) {
sign = 1;
if (v < 0)
sign = -1, v = -v;
for (; v > 0; v = v / base)
a.push_back(v % base);
}
bigint operator+(const bigint &v) const {
if (sign == v.sign) {
bigint res = v;
for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
if (i == (int) res.a.size())
res.a.push_back(0);
res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
carry = res.a[i] >= base;
if (carry)
res.a[i] -= base;
}
return res;
}
return *this - (-v);
}
bigint operator-(const bigint &v) const {
if (sign == v.sign) {
if (abs() >= v.abs()) {
bigint res = *this;
for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
carry = res.a[i] < 0;
if (carry)
res.a[i] += base;
}
res.trim();
return res;
}
return -(v - *this);
}
return *this + (-v);
}
void operator*=(int v) {
if (v < 0)
sign = -sign, v = -v;
for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
if (i == (int) a.size())
a.push_back(0);
long long cur = a[i] * (long long) v + carry;
carry = (int) (cur / base);
a[i] = (int) (cur % base);
//asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
}
trim();
}
bigint operator*(int v) const {
bigint res = *this;
res *= v;
return res;
}
friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
int norm = base / (b1.a.back() + 1);
bigint a = a1.abs() * norm;
bigint b = b1.abs() * norm;
bigint q, r;
q.a.resize(a.a.size());
for (int i = a.a.size() - 1; i >= 0; i--) {
r *= base;
r += a.a[i];
int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
int d = ((long long) base * s1 + s2) / b.a.back();
r -= b * d;
while (r < 0)
r += b, --d;
q.a[i] = d;
}
q.sign = a1.sign * b1.sign;
r.sign = a1.sign;
q.trim();
r.trim();
return make_pair(q, r / norm);
}
bigint operator/(const bigint &v) const {
return divmod(*this, v).first;
}
bigint operator%(const bigint &v) const {
return divmod(*this, v).second;
}
void operator/=(int v) {
if (v < 0)
sign = -sign, v = -v;
for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
long long cur = a[i] + rem * (long long) base;
a[i] = (int) (cur / v);
rem = (int) (cur % v);
}
trim();
}
bigint operator/(int v) const {
bigint res = *this;
res /= v;
return res;
}
int operator%(int v) const {
if (v < 0)
v = -v;
int m = 0;
for (int i = a.size() - 1; i >= 0; --i)
m = (a[i] + m * (long long) base) % v;
return m * sign;
}
void operator+=(const bigint &v) {
*this = *this + v;
}
void operator-=(const bigint &v) {
*this = *this - v;
}
void operator*=(const bigint &v) {
*this = *this * v;
}
void operator/=(const bigint &v) {
*this = *this / v;
}
bool operator<(const bigint &v) const {
if (sign != v.sign)
return sign < v.sign;
if (a.size() != v.a.size())
return a.size() * sign < v.a.size() * v.sign;
for (int i = a.size() - 1; i >= 0; i--)
if (a[i] != v.a[i])
return a[i] * sign < v.a[i] * sign;
return false;
}
bool operator>(const bigint &v) const {
return v < *this;
}
bool operator<=(const bigint &v) const {
return !(v < *this);
}
bool operator>=(const bigint &v) const {
return !(*this < v);
}
bool operator==(const bigint &v) const {
return !(*this < v) && !(v < *this);
}
bool operator!=(const bigint &v) const {
return *this < v || v < *this;
}
void trim() {
while (!a.empty() && !a.back())
a.pop_back();
if (a.empty())
sign = 1;
}
bool isZero() const {
return a.empty() || (a.size() == 1 && !a[0]);
}
bigint operator-() const {
bigint res = *this;
res.sign = -sign;
return res;
}
bigint abs() const {
bigint res = *this;
res.sign *= res.sign;
return res;
}
long long longValue() const {
long long res = 0;
for (int i = a.size() - 1; i >= 0; i--)
res = res * base + a[i];
return res * sign;
}
friend bigint gcd(const bigint &a, const bigint &b) {
return b.isZero() ? a : gcd(b, a % b);
}
friend bigint lcm(const bigint &a, const bigint &b) {
return a / gcd(a, b) * b;
}
void read(const string &s) {
sign = 1;
a.clear();
int pos = 0;
while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
if (s[pos] == '-')
sign = -sign;
++pos;
}
for (int i = s.size() - 1; i >= pos; i -= base_digits) {
int x = 0;
for (int j = max(pos, i - base_digits + 1); j <= i; j++)
x = x * 10 + s[j] - '0';
a.push_back(x);
}
trim();
}
friend istream& operator>>(istream &stream, bigint &v) {
string s;
stream >> s;
v.read(s);
return stream;
}
friend ostream& operator<<(ostream &stream, const bigint &v) {
if (v.sign == -1)
stream << '-';
stream << (v.a.empty() ? 0 : v.a.back());
for (int i = (int) v.a.size() - 2; i >= 0; --i)
stream << setw(base_digits) << setfill('0') << v.a[i];
return stream;
}
static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
vector<long long> p(max(old_digits, new_digits) + 1);
p[0] = 1;
for (int i = 1; i < (int) p.size(); i++)
p[i] = p[i - 1] * 10;
vector<int> res;
long long cur = 0;
int cur_digits = 0;
for (int i = 0; i < (int) a.size(); i++) {
cur += a[i] * p[cur_digits];
cur_digits += old_digits;
while (cur_digits >= new_digits) {
res.push_back(int(cur % p[new_digits]));
cur /= p[new_digits];
cur_digits -= new_digits;
}
}
res.push_back((int) cur);
while (!res.empty() && !res.back())
res.pop_back();
return res;
}
typedef vector<long long> vll;
static vll karatsubaMultiply(const vll &a, const vll &b) {
int n = a.size();
vll res(n + n);
if (n <= 32) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
res[i + j] += a[i] * b[j];
return res;
}
int k = n >> 1;
vll a1(a.begin(), a.begin() + k);
vll a2(a.begin() + k, a.end());
vll b1(b.begin(), b.begin() + k);
vll b2(b.begin() + k, b.end());
vll a1b1 = karatsubaMultiply(a1, b1);
vll a2b2 = karatsubaMultiply(a2, b2);
for (int i = 0; i < k; i++)
a2[i] += a1[i];
for (int i = 0; i < k; i++)
b2[i] += b1[i];
vll r = karatsubaMultiply(a2, b2);
for (int i = 0; i < (int) a1b1.size(); i++)
r[i] -= a1b1[i];
for (int i = 0; i < (int) a2b2.size(); i++)
r[i] -= a2b2[i];
for (int i = 0; i < (int) r.size(); i++)
res[i + k] += r[i];
for (int i = 0; i < (int) a1b1.size(); i++)
res[i] += a1b1[i];
for (int i = 0; i < (int) a2b2.size(); i++)
res[i + n] += a2b2[i];
return res;
}
bigint operator*(const bigint &v) const {
vector<int> a6 = convert_base(this->a, base_digits, 6);
vector<int> b6 = convert_base(v.a, base_digits, 6);
vll a(a6.begin(), a6.end());
vll b(b6.begin(), b6.end());
while (a.size() < b.size())
a.push_back(0);
while (b.size() < a.size())
b.push_back(0);
while (a.size() & (a.size() - 1))
a.push_back(0), b.push_back(0);
vll c = karatsubaMultiply(a, b);
bigint res;
res.sign = sign * v.sign;
for (int i = 0, carry = 0; i < (int) c.size(); i++) {
long long cur = c[i] + carry;
res.a.push_back((int) (cur % 1000000));
carry = (int) (cur / 1000000);
}
res.a = convert_base(res.a, 6, base_digits);
res.trim();
return res;
}
};
//use : bigint var;
//template for biginit over
int main()
{
bigint var=10909000890789;
cout<<var;
return 0;
}

How to add two numbers without using ++ or + or another arithmetic operator

How do I add two numbers without using ++ or + or any other arithmetic operator?
It was a question asked a long time ago in some campus interview. Anyway, today someone asked a question regarding some bit-manipulations, and in answers a beautiful quide Stanford bit twiddling was referred. I spend some time studying it and thought that there actually might be an answer to the question. I don't know, I could not find one. Does an answer exist?
This is something I have written a while ago for fun. It uses a two's complement representation and implements addition using repeated shifts with a carry bit, implementing other operators mostly in terms of addition.
#include <stdlib.h> /* atoi() */
#include <stdio.h> /* (f)printf */
#include <assert.h> /* assert() */
int add(int x, int y) {
int carry = 0;
int result = 0;
int i;
for(i = 0; i < 32; ++i) {
int a = (x >> i) & 1;
int b = (y >> i) & 1;
result |= ((a ^ b) ^ carry) << i;
carry = (a & b) | (b & carry) | (carry & a);
}
return result;
}
int negate(int x) {
return add(~x, 1);
}
int subtract(int x, int y) {
return add(x, negate(y));
}
int is_even(int n) {
return !(n & 1);
}
int divide_by_two(int n) {
return n >> 1;
}
int multiply_by_two(int n) {
return n << 1;
}
int multiply(int x, int y) {
int result = 0;
if(x < 0 && y < 0) {
return multiply(negate(x), negate(y));
}
if(x >= 0 && y < 0) {
return multiply(y, x);
}
while(y > 0) {
if(is_even(y)) {
x = multiply_by_two(x);
y = divide_by_two(y);
} else {
result = add(result, x);
y = add(y, -1);
}
}
return result;
}
int main(int argc, char **argv) {
int from = -100, to = 100;
int i, j;
for(i = from; i <= to; ++i) {
assert(0 - i == negate(i));
assert(((i % 2) == 0) == is_even(i));
assert(i * 2 == multiply_by_two(i));
if(is_even(i)) {
assert(i / 2 == divide_by_two(i));
}
}
for(i = from; i <= to; ++i) {
for(j = from; j <= to; ++j) {
assert(i + j == add(i, j));
assert(i - j == subtract(i, j));
assert(i * j == multiply(i, j));
}
}
return 0;
}
Or, rather than Jason's bitwise approach, you can calculate many bits in parallel - this should run much faster with large numbers. In each step figure out the carry part and the part that is sum. You attempt to add the carry to the sum, which could cause carry again - hence the loop.
>>> def add(a, b):
while a != 0:
# v carry portion| v sum portion
a, b = ((a & b) << 1), (a ^ b)
print b, a
return b
when you add 1 and 3, both numbers have the 1 bit set, so the sum of that 1+1 carries. The next step you add 2 to 2 and that carries into the correct sum four. That causes an exit
>>> add(1,3)
2 2
4 0
4
Or a more complex example
>>> add(45, 291)
66 270
4 332
8 328
16 320
336
Edit:
For it to work easily on signed numbers you need to introduce an upper limit on a and b
>>> def add(a, b):
while a != 0:
# v carry portion| v sum portion
a, b = ((a & b) << 1), (a ^ b)
a &= 0xFFFFFFFF
b &= 0xFFFFFFFF
print b, a
return b
Try it on
add(-1, 1)
to see a single bit carry up through the entire range and overflow over 32 iterations
4294967294 2
4294967292 4
4294967288 8
...
4294901760 65536
...
2147483648 2147483648
0 0
0L
int Add(int a, int b)
{
while (b)
{
int carry = a & b;
a = a ^ b;
b = carry << 1;
}
return a;
}
You could transform an adder circuit into an algorithm. They only do bitwise operations =)
Well, to implement an equivalent with boolean operators is quite simple: you do a bit-by-bit sum (which is an XOR), with carry (which is an AND). Like this:
int sum(int value1, int value2)
{
int result = 0;
int carry = 0;
for (int mask = 1; mask != 0; mask <<= 1)
{
int bit1 = value1 & mask;
int bit2 = value2 & mask;
result |= mask & (carry ^ bit1 ^ bit2);
carry = ((bit1 & bit2) | (bit1 & carry) | (bit2 & carry)) << 1;
}
return result;
}
You've already gotten a couple bit manipulation answers. Here's something different.
In C, arr[ind] == *(arr + ind). This lets us do slightly confusing (but legal) things like int arr = { 3, 1, 4, 5 }; int val = 0[arr];.
So we can define a custom add function (without explicit use of an arithmetic operator) thusly:
unsigned int add(unsigned int const a, unsigned int const b)
{
/* this works b/c sizeof(char) == 1, by definition */
char * const aPtr = (char *)a;
return (int) &(aPtr[b]);
}
Alternately, if we want to avoid this trick, and if by arithmetic operator they include |, &, and ^ (so direct bit manipulation is not allowed) , we can do it via lookup table:
typedef unsigned char byte;
const byte lut_add_mod_256[256][256] = {
{ 0, 1, 2, /*...*/, 255 },
{ 1, 2, /*...*/, 255, 0 },
{ 2, /*...*/, 255, 0, 1 },
/*...*/
{ 254, 255, 0, 1, /*...*/, 253 },
{ 255, 0, 1, /*...*/, 253, 254 },
};
const byte lut_add_carry_256[256][256] = {
{ 0, 0, 0, /*...*/, 0 },
{ 0, 0, /*...*/, 0, 1 },
{ 0, /*...*/, 0, 1, 1 },
/*...*/
{ 0, 0, 1, /*...*/, 1 },
{ 0, 1, 1, /*...*/, 1 },
};
void add_byte(byte const a, byte const b, byte * const sum, byte * const carry)
{
*sum = lut_add_mod_256[a][b];
*carry = lut_add_carry_256[a][b];
}
unsigned int add(unsigned int a, unsigned int b)
{
unsigned int sum;
unsigned int carry;
byte * const aBytes = (byte *) &a;
byte * const bBytes = (byte *) &b;
byte * const sumBytes = (byte *) ∑
byte * const carryBytes = (byte *) &carry;
byte const test[4] = { 0x12, 0x34, 0x56, 0x78 };
byte BYTE_0, BYTE_1, BYTE_2, BYTE_3;
/* figure out endian-ness */
if (0x12345678 == *(unsigned int *)test)
{
BYTE_0 = 3;
BYTE_1 = 2;
BYTE_2 = 1;
BYTE_3 = 0;
}
else
{
BYTE_0 = 0;
BYTE_1 = 1;
BYTE_2 = 2;
BYTE_3 = 3;
}
/* assume 4 bytes to the unsigned int */
add_byte(aBytes[BYTE_0], bBytes[BYTE_0], &sumBytes[BYTE_0], &carryBytes[BYTE_0]);
add_byte(aBytes[BYTE_1], bBytes[BYTE_1], &sumBytes[BYTE_1], &carryBytes[BYTE_1]);
if (carryBytes[BYTE_0] == 1)
{
if (sumBytes[BYTE_1] == 255)
{
sumBytes[BYTE_1] = 0;
carryBytes[BYTE_1] = 1;
}
else
{
add_byte(sumBytes[BYTE_1], 1, &sumBytes[BYTE_1], &carryBytes[BYTE_0]);
}
}
add_byte(aBytes[BYTE_2], bBytes[BYTE_2], &sumBytes[BYTE_2], &carryBytes[BYTE_2]);
if (carryBytes[BYTE_1] == 1)
{
if (sumBytes[BYTE_2] == 255)
{
sumBytes[BYTE_2] = 0;
carryBytes[BYTE_2] = 1;
}
else
{
add_byte(sumBytes[BYTE_2], 1, &sumBytes[BYTE_2], &carryBytes[BYTE_1]);
}
}
add_byte(aBytes[BYTE_3], bBytes[BYTE_3], &sumBytes[BYTE_3], &carryBytes[BYTE_3]);
if (carryBytes[BYTE_2] == 1)
{
if (sumBytes[BYTE_3] == 255)
{
sumBytes[BYTE_3] = 0;
carryBytes[BYTE_3] = 1;
}
else
{
add_byte(sumBytes[BYTE_3], 1, &sumBytes[BYTE_3], &carryBytes[BYTE_2]);
}
}
return sum;
}
All arithmetic operations decompose to bitwise operations to be implemented in electronics, using NAND, AND, OR, etc. gates.
Adder composition can be seen here.
For unsigned numbers, use the same addition algorithm as you learned in first class, but for base 2 instead of base 10. Example for 3+2 (base 10), i.e 11+10 in base 2:
1 ‹--- carry bit
0 1 1 ‹--- first operand (3)
+ 0 1 0 ‹--- second operand (2)
-------
1 0 1 ‹--- total sum (calculated in three steps)
If you're feeling comedic, there's always this spectacularly awful approach for adding two (relatively small) unsigned integers. No arithmetic operators anywhere in your code.
In C#:
static uint JokeAdder(uint a, uint b)
{
string result = string.Format(string.Format("{{0,{0}}}{{1,{1}}}", a, b), null, null);
return result.Length;
}
In C, using stdio (replace snprintf with _snprintf on Microsoft compilers):
#include <stdio.h>
unsigned int JokeAdder(unsigned int a, unsigned int b)
{
return snprintf(NULL, 0, "%*.*s%*.*s", a, a, "", b, b, "");
}
Here is a compact C solution. Sometimes recursion is more readable than loops.
int add(int a, int b){
if (b == 0) return a;
return add(a ^ b, (a & b) << 1);
}
#include<stdio.h>
int add(int x, int y) {
int a, b;
do {
a = x & y;
b = x ^ y;
x = a << 1;
y = b;
} while (a);
return b;
}
int main( void ){
printf( "2 + 3 = %d", add(2,3));
return 0;
}
short int ripple_adder(short int a, short int b)
{
short int i, c, s, ai, bi;
c = s = 0;
for (i=0; i<16; i++)
{
ai = a & 1;
bi = b & 1;
s |= (((ai ^ bi)^c) << i);
c = (ai & bi) | (c & (ai ^ bi));
a >>= 1;
b >>= 1;
}
s |= (c << i);
return s;
}
## to add or subtract without using '+' and '-' ##
#include<stdio.h>
#include<conio.h>
#include<process.h>
void main()
{
int sub,a,b,carry,temp,c,d;
clrscr();
printf("enter a and b:");
scanf("%d%d",&a,&b);
c=a;
d=b;
while(b)
{
carry=a&b;
a=a^b;
b=carry<<1;
}
printf("add(%d,%d):%d\n",c,d,a);
temp=~d+1; //take 2's complement of b and add it with a
sub=c+temp;
printf("diff(%d,%d):%d\n",c,d,temp);
getch();
}
The following would work.
x - (-y)
This can be done recursively:
int add_without_arithm_recursively(int a, int b)
{
if (b == 0)
return a;
int sum = a ^ b; // add without carrying
int carry = (a & b) << 1; // carry, but don’t add
return add_without_arithm_recursively(sum, carry); // recurse
}
or iteratively:
int add_without_arithm_iteratively(int a, int b)
{
int sum, carry;
do
{
sum = a ^ b; // add without carrying
carry = (a & b) << 1; // carry, but don’t add
a = sum;
b = carry;
} while (b != 0);
return a;
}
Code to implement add,multiplication without using +,* operator;
for subtraction pass 1's complement +1 of number to add function
#include<stdio.h>
unsigned int add(unsigned int x,unsigned int y)
{
int carry=0;
while (y != 0)
{
carry = x & y;
x = x ^ y;
y = carry << 1;
}
return x;
}
int multiply(int a,int b)
{
int res=0;
int i=0;
int large= a>b ? a :b ;
int small= a<b ? a :b ;
for(i=0;i<small;i++)
{
res = add(large,res);
}
return res;
}
int main()
{
printf("Sum :: %u,Multiply is :: %d",add(7,15),multiply(111,111));
return 0;
}
The question asks how to add two numbers so I don't understand why all the solutions offers the addition of two integers? What if the two numbers were floats i.e. 2.3 + 1.8 are they also not considered numbers? Either the question needs to be revised or the answers.
For floats I believe the numbers should be broken into their components i.e. 2.3 = 2 + 0.3 then the 0.3 should be converted to an integer representation by multiplying with its exponent factor i.e 0.3 = 3 * 10^-1 do the same for the other number and then add the integer segment using one of the bit shift methods given as a solution above handling situations for carry over to the unit digits location i.e. 2.7 + 3.3 = 6.0 = 2+3+0.7+0.3 = 2 + 3 + 7x10^-1 + 3x10^-1 = 2 + 3 + 10^10^-1 (this can be handled as two separate additions 2+3=5 and then 5+1=6)
With given answers above, it can be done in single line code:
int add(int a, int b) {
return (b == 0) ? a : add(a ^ b, (a & b) << 1);
}
You can use double negetive to add two integers for example:
int sum2(int a, int b){
return -(-a-b);
}
Without using any operators adding two integers can be done in different ways as follows:
int sum_of_2 (int a, int b){
int sum=0, carry=sum;
sum =a^b;
carry = (a&b)<<1;
return (b==0)? a: sum_of_2(sum, carry);
}
// Or you can just do it in one line as follows:
int sum_of_2 (int a, int b){
return (b==0)? a: sum_of_2(a^b, (a&b)<<1);
}
// OR you can use the while loop instead of recursion function as follows
int sum_of_2 (int a, int b){
if(b==0){
return a;
}
while(b!=0){
int sum = a^b;
int carry = (a&b)<<1;
a= sum;
b=carry;
}
return a;
}
int add_without_arithmatic(int a, int b)
{
int sum;
char *p;
p = (char *)a;
sum = (int)&p[b];
printf("\nSum : %d",sum);
}