Нужен перевод строки в 64 бит целое. Компилятор поддерживает только 32 бит целые числа, поэтому на выходе нужен просто массив байт. Киньте пожалуйста алгоритм или ссылку кто знает.
Здравствуйте, Аноним, Вы писали:
А>Нужен перевод строки в 64 бит целое. Компилятор поддерживает только 32 бит целые числа, поэтому на выходе нужен просто массив байт. Киньте пожалуйста алгоритм или ссылку кто знает.
Думаю многие знают, но лень

Вот тебе примерчег:
#include <malloc.h>
void throw_overflow() { throw "ints overflow"; }
void throw_bad_syntax() { throw "invalid syntax"; }
#define stack_alloc(n,t) (t*)alloca(n*sizeof(t))
typedef unsigned uint;
const uint uint_bits=8*sizeof(uint);
const uint last_bit =1<<(uint_bits-1);
const uint uint_max =~0;
const uint mask_nlb =~last_bit;
int get_add_carry(uint a,uint b,uint c=0) {
int cc=0;
if (a&last_bit) ++cc;
if (b&last_bit) ++cc;
a&=mask_nlb; b&=mask_nlb;
if ((a+b+c)&last_bit) ++cc;
return cc>1;
}
void ints_clr(int n,uint *r) { for(int i=0;i<n;i++) r[i]=0; }
void ints_mov(int n,uint *r,uint *a) { for(int i=0;i<n;i++) r[i]=a[i]; }
void ints_movzx(int n,uint *r,int a) { r[0]=(uint)a; for(int i=1;i<n;i++) r[i]=0; }
uint ints_addzx(int n,uint *r,uint *a,uint b,uint c=0) {
int cc=get_add_carry(a[0],b,c); r[0]=a[0]+b+c; c=cc;
for(int i=1;c && i<n;i++) { c=(a[i]==uint_max); r[i]=a[i]+1; }
return c;
}
uint ints_add(int n,uint *r,uint *a,uint *b,uint c=0) {
for(int i=0;i<n;i++) { int cc=get_add_carry(a[i],b[i],c); r[i]=a[i]+b[i]+c; c=cc; }
return c;
}
void ints_mul10(int n,uint *x) {
uint *t=stack_alloc(n,uint);
uint c1=ints_add(n,t,x,x);
ints_mov(n,x,t);
c1+=ints_add(n,t,t,t);
c1+=ints_add(n,t,t,t);
c1+=ints_add(n,x,x,t);
if (c1>0) throw_overflow();
}
int is_space(char c) { return c>0 && c<=32; }
int is_digit(char c) { return c>='0' && c<='9'; }
int ints_ldstr(int n,uint *x,const char* s) {
ints_clr(n,x);
int p=0;while(is_space(s[p])) p++;
if (!is_digit(s[p])) throw_bad_syntax();
ints_movzx(n,x,s[p++]-'0');
while(is_digit(s[p])) {
ints_mul10(n,x);
if (ints_addzx(n,x,x,s[p]-'0')) throw_overflow();
p++;
}
return p;
}
// тест на вшивость
#include <iostream>
using namespace std;
typedef long long int64; // gcc
//typedef __int64 int64; // vc
int main(int argc, const char **argv) {
int64 x; int n=sizeof(x)/sizeof(uint);
ints_ldstr(n,(uint*)&x,"1234567890123456789"); cout<<x<<endl;
x=1234567890123456789LL; cout<<x<<endl;
return 0;
}
ps: к сожалению перенос от сложения в C/C++ не задуман, так что get_add_carry это костыль. на асме всё гораздо приятнее смотрится
Здравствуйте, Аноним, Вы писали:
Вот немного оптимизированный вариант *10: на одну операцию меньше
void ints_mul10(int n,uint *x) {
uint *t=stack_alloc(n,uint),
c=ints_add(n,x,x,x);
c+=ints_add(n,t,x,x);
c+=ints_add(n,t,t,t);
c+=ints_add(n,x,x,t);
if (c) throw_overflow();
}
А>Думаю многие знают, но лень
Вот тебе примерчег:
Спасибо, вот еще вариант:
char str[] = "12345678901234567890"; // строка на входе
unsigned char uc[8]; // массив на выходе
unsigned long l = 0;
unsigned long m = 0;
unsigned long h = 0;
unsigned char carry;
for( char *c = str; *c; c++ )
{
l += *c - '0';
if( *(c + 1) )
{
l *= 10;
carry = (unsigned char)((l & 0xFF000000) >> 24);
l &= 0x00FFFFFF;
m *= 10;
m += carry;
carry = (unsigned char)((m & 0xFF000000) >> 24);
m &= 0x00FFFFFF;
h *= 10;
h += carry;
}
}
uc[7] = (unsigned char)l; l >>= 8;
uc[6] = (unsigned char)l; l >>= 8;
uc[5] = (unsigned char)l;
uc[4] = (unsigned char)m; m >>= 8;
uc[3] = (unsigned char)m; m >>= 8;
uc[2] = (unsigned char)m;
uc[1] = (unsigned char)h; h >>= 8;
uc[0] = (unsigned char)h;
Здравствуйте, xscream, Вы писали:
А>>Думаю многие знают, но лень
Вот тебе примерчег:
X>Спасибо, вот еще вариант:
Не буду хвастаться, но замечу что у меня есть проверка на переполнение и возможность работать int128, int256 и т.д.