Re: Перевод строки в 64 бит целое
От: Аноним  
Дата: 22.02.08 11:17
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Нужен перевод строки в 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 это костыль. на асме всё гораздо приятнее смотрится
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.