首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >大量存储为向量,提高了性能。

大量存储为向量,提高了性能。
EN

Code Review用户
提问于 2020-04-18 11:20:16
回答 1查看 52关注 0票数 4

我做了一个代码来初始化字符向量,用随机数表示超过20.000位数的很大的数字。加法和乘法是正确的,但我的代码太慢(1分钟)。我知道我可以将char改为64 int,一次用19个数字进行操作,而不是一次用一个数字,但我不知道如何做到这一点,而不改变当前的输出是正确的。

谢谢你的帮忙

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>

unsigned int seed;

int newrandom() {
  seed = (214013*seed+2531011);
  return (seed>>13);
}


void LongNumInit( char *L, unsigned N )
{
  for ( int i=0; i< N; i++ ) 
  {
    L[i] = newrandom() % 10;
  }
}

void PrintNumber( char *L, unsigned N, char *Name )
{
  printf("%s:", Name);
  for ( int i=N; i>0; i-- ) 
  {
    printf("%d", L[i-1]);
  }
  printf("\n");
}


void ValueSet( char *L, unsigned N, char digit )
{
  for ( int i=0; i< N; i++ ) 
  {
    L[i] = digit;
  }
}


void CPNumber( char *Vin, char *Vout, unsigned N )
{
  for ( int i=0; i< N; i++ ) 
  {
    Vout[i] = Vin[i];
  }
}

char Add( char *Vin1, char *Vin2, char *Vout, unsigned N )
{
  char CARRY = 0;
  for ( int i=0; i< N; i++ ) 
  {
    char R = Vin1[i] + Vin2[i] + CARRY;
    if ( R <= 9 )
    {
      Vout[i] = R; CARRY = 0;
    }
    else
    {
      Vout[i] = R-10; CARRY = 1;
    }
  }
  return CARRY;
}


char DigitAddition( char *V, char digit, unsigned N )
{
  int i=0;
  char R = V[0] + digit;
  if (R < 10)
  {
    V[0] = R; return 0;
  }

  V[0] = R-10;
  char CARRY = 1;
  i = 1;
  while ( CARRY && i < N ) 
  {
    if ( V[i] < 9 )
    {
      V[i] = V[i] + 1; CARRY = 0;
    }
    else 
    {
      V[i] = 0; i++;
    }
  }
  return CARRY;
}


char AddInHorizontal( char *Vin, char *Vout, unsigned N )
{
  char CARRY = 0;
  ValueSet ( Vout, N, 0 );
  for ( int i=0; i< N; i++ ) 
  {
    DigitAddition ( Vout, Vin[i], N );
  }
  return 0;
}

char MultiplyConst( char *V, unsigned N, char digit )
{
  char CARRY = 0;
  for ( int i=0; i< N; i++ ) 
  {
    char R = V[i] * digit + CARRY;
    CARRY = R / 10;
    R = R - CARRY*10;
    V[i] = R;
  }
  return CARRY; // may be from 0 to 9
}

void Mult( char *Vin1, char *Vin2, char *VoutH, char *VoutL,  unsigned N )
{ 

  unsigned char *TEMP= (unsigned char*) malloc( 2*N*sizeof(unsigned char) );
  unsigned char *RES = (unsigned char*) malloc( 2*N*sizeof(unsigned char) );

  ValueSet  ( RES, 2*N, 0 );    // Set RES to 0

  for ( int i=0; i<N; i++ ) 
  { 
    ValueSet  ( TEMP, 2*N, 0 );            
    CPNumber ( Vin1, TEMP+i, N );         
    MultiplyConst( TEMP, 2*N, Vin2[i] );
    Add ( TEMP, RES, RES, 2*N ); // TEMP + RES -> RES
  }

  CPNumber ( RES,   VoutL, N ); 
  CPNumber ( RES+N, VoutH, N ); 
}


int main (int argc, char **argv)
{
  int i, sum1, sum2, sum3, N=20000;

  seed = 12345;

  if (argc>1) { N    = atoi(argv[1]); }
  if (argc>2) { Rep  = atoi(argv[2]); }

  unsigned char *V1= (unsigned char*) malloc( N*sizeof(unsigned char) );
  unsigned char *V2= (unsigned char*) malloc( N*sizeof(unsigned char) );
  unsigned char *V3= (unsigned char*) malloc( N*sizeof(unsigned char) );
  unsigned char *V4= (unsigned char*) malloc( N*sizeof(unsigned char) );

  LongNumInit ( V1, N );
  LongNumInit ( V2, N );
  LongNumInit ( V3, N );

  Add ( V1, V2, V4, N );
  Mult ( V3, V4, V2, V1, N );
  AddInHorizontal ( V1, V2, N );
  DigitAddition ( V3, V2[0], N );

  PrintNumber( V1, 32, "V1" );
  PrintNumber( V2, 32, "V2" );
  PrintNumber( V3, 32, "V3" );
  PrintNumber( V4, 32, "V4" );

  free(V1);
  free(V2);
  free(V3);
  free(V4);
  return 0;
}

```
代码语言:javascript
复制
EN

回答 1

Code Review用户

发布于 2020-04-18 14:09:25

祝贺您的代码已经准备好进行检查了!下面是一些关于如何改进这一点的想法:

  1. 您已经将此代码标记为CC++。在我看来,这看起来完全像C代码。如果是,请编辑标签。如果这需要同时用作CC++代码,则需要指定应用哪些其他约束。
  2. C代码通常为函数名使用snake_case编写。对于在共享数据类型上操作的函数模块,经常使用短前缀。由于您将对象称为"LongNum",我建议您将函数重命名为使用lnum_lngn_lnm_之类的前缀。char添加( char *Vin1,char *Vin2,char *Vout,unsigned N) {.}变为char lnum_add(char * ln1,char *ln2,char *lnout,unsigned N){.}
  3. 创建LongNum需要分配内存。默认情况下,该操作可以也应该是库的一部分。(您可能希望为“从用户提供的内存初始化longnum”编写一个函数,但我怀疑您是否需要它。)因此,您不应该直接执行malloc()free()调用,而是应该调用lnum_new_random()lnum_delete()
  4. 我认为没有理由避免使用C++命名方案,因此我建议将您的创建/分配函数称为new和免费函数delete
  5. 关于(4),我认为一个好的库应该能够以各种方式创建对象。特别是一个随机值,一个固定的值,如0或1,任意整数值,双倍值,可能来自字符串的值,和/或输入流中的值。Lnum_new_random(未签名的max_digits) lnum_new_zero(未签名的max_digits) lnum_new_from_int(未签名的max_digits,long init_val) lnum_new_from_unsigned(未签名的max_digits,未签名的long init_val) lnum_new_from_double(未签名的max_digits,long double init_val) lnum_new_from_string(未签名的max_digits,const char * str) lnum_new_from_file(未签名的lnum_new_from_int,文件*输入)lnum_new_from_file(原始的LNUM)
  6. 与其传递参数N来指定数据类型的最大长度,不如构建一个struct来存储信息。首先,您可以用max_digits值和指向数字缓冲区开头的指针定义一个结构。更高级的版本将消除指针,并在max_digits值之后立即分配数字缓冲区。struct {无符号的max_digits;char *位;};通过这样做,您可以决定将对象作为指针传递还是以结构值的形式传递更有意义。因此,您需要一个您控制的命名类型,而不仅仅是让用户在一个char *指针周围传递:ty胡枝子结构LNUM;// if struct LNUM包含数字作为指针,typedef结构LNUM * LNUM;// if struct LNUM包括数组数字
  7. 您的PrintNumber函数提供了提取数字的唯一方法。它对基、输出流和格式进行了硬编码。我建议编写一个函数,将一个LNUM发送到流上,另一个函数用提供的基将一个LNUM写入字符串缓冲区。size_t lnum_formatted_length(LNUM );lnum_format_to_string(LNUM,char * buffer,size_t max_chars);
  8. 与其将N视为常量,不如动态计算N是否是错误的?乘法函数返回两个数字,"low“和"high",每个都是N大小。为什么不简单地返回一个具有由乘法函数确定的正确大小的数字呢?也许它需要更多的数字,也许它不需要。
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/240732

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档