⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 number.c

📁 操作系统源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
  /* Check for correct numbers. */  if (is_zero (num2)) return -1;  /* Calculate final scale. */  rscale = MAX (num1->n_scale, num2->n_scale+scale);  init_num (&temp);    /* Calculate it. */  bc_divide (num1, num2, &temp, scale);  bc_multiply (temp, num2, &temp, rscale);  bc_sub (num1, temp, result);  free_num (&temp);  return 0;	/* Everything is OK. */}/* Raise NUM1 to the NUM2 power.  The result is placed in RESULT.   Maximum exponent is LONG_MAX.  If a NUM2 is not an integer,   only the integer part is used.  */voidbc_raise (num1, num2, result, scale)     bc_num num1, num2, *result;     int scale;{   bc_num temp, power;   long exponent;   int rscale;   char neg;   /* Check the exponent for scale digits and convert to a long. */   if (num2->n_scale != 0)     rt_warn ("non-zero scale in exponent");   exponent = num2long (num2);   if (exponent == 0 && (num2->n_len > 1 || num2->n_value[0] != 0))       rt_error ("exponent too large in raise");   /* Special case if exponent is a zero. */   if (exponent == 0)     {       free_num (result);       *result = copy_num (_one_);       return;     }   /* Other initializations. */   if (exponent < 0)     {       neg = TRUE;       exponent = -exponent;       rscale = scale;     }   else     {       neg = FALSE;       rscale = MIN (num1->n_scale*exponent, MAX(scale, num1->n_scale));     }   temp = copy_num (_one_);   power = copy_num (num1);   /* Do the calculation. */   while (exponent != 0)     {       if (exponent & 1 != 0) 	 bc_multiply (temp, power, &temp, rscale);       bc_multiply (power, power, &power, rscale);       exponent = exponent >> 1;     }      /* Assign the value. */   if (neg)     {       bc_divide (_one_, temp, result, rscale);       free_num (&temp);     }   else     {       free_num (result);       *result = temp;     }   free_num (&power);}/* Take the square root NUM and return it in NUM with SCALE digits   after the decimal place. */int bc_sqrt (num, scale)     bc_num *num;     int scale;{  int rscale, cmp_res, done;  int cscale;  bc_num guess, guess1, point5;  /* Initial checks. */  cmp_res = bc_compare (*num, _zero_);  if (cmp_res < 0)    return 0;		/* error */  else    {      if (cmp_res == 0)	{	  free_num (num);	  *num = copy_num (_zero_);	  return 1;	}    }  cmp_res = bc_compare (*num, _one_);  if (cmp_res == 0)    {      free_num (num);      *num = copy_num (_one_);      return 1;    }  /* Initialize the variables. */  rscale = MAX (scale, (*num)->n_scale);  cscale = rscale + 2;  init_num (&guess);  init_num (&guess1);  point5 = new_num (1,1);  point5->n_value[1] = 5;      /* Calculate the initial guess. */  if (cmp_res < 0)    /* The number is between 0 and 1.  Guess should start at 1. */    guess = copy_num (_one_);  else    {      /* The number is greater than 1.  Guess should start at 10^(exp/2). */      int2num (&guess,10);      int2num (&guess1,(*num)->n_len);      bc_multiply (guess1, point5, &guess1, rscale);      guess1->n_scale = 0;      bc_raise (guess, guess1, &guess, rscale);      free_num (&guess1);    }    /* Find the square root using Newton's algorithm. */  done = FALSE;  while (!done)    {      free_num (&guess1);      guess1 = copy_num (guess);      bc_divide (*num,guess,&guess,cscale);      bc_add (guess,guess1,&guess);      bc_multiply (guess,point5,&guess,cscale);      cmp_res = _do_compare (guess,guess1,FALSE,TRUE);      if (cmp_res == 0) done = TRUE;    }    /* Assign the number and clean up. */  free_num (num);  bc_divide (guess,_one_,num,rscale);  free_num (&guess);  free_num (&guess1);  free_num (&point5);  return 1;}/* The following routines provide output for bcd numbers package   using the rules of POSIX bc for output. *//* This structure is used for saving digits in the conversion process. */typedef struct stk_rec {	long  digit;	struct stk_rec *next;} stk_rec;/* The reference string for digits. */char ref_str[] = "0123456789ABCDEF";/* A special output routine for "multi-character digits."  Exactly   SIZE characters must be output for the value VAL.  If SPACE is   non-zero, we must output one space before the number.  OUT_CHAR   is the actual routine for writing the characters. */voidout_long (val, size, space, out_char)     long val;     int size, space;#ifdef __STDC__     void (*out_char)(int);#else     void (*out_char)();#endif{  char digits[40];  int len, ix;  if (space) (*out_char) (' ');  sprintf (digits, "%ld", val);  len = strlen (digits);  while (size > len)    {      (*out_char) ('0');      size--;    }  for (ix=0; ix < len; ix++)    (*out_char) (digits[ix]);}/* Output of a bcd number.  NUM is written in base O_BASE using OUT_CHAR   as the routine to do the actual output of the characters. */voidout_num (num, o_base, out_char)     bc_num num;     int o_base;#ifdef __STDC__     void (*out_char)(int);#else     void (*out_char)();#endif{  char *nptr;  int  index, fdigit, pre_space;  stk_rec *digits, *temp;  bc_num int_part, frac_part, base, cur_dig, t_num, max_o_digit;  /* The negative sign if needed. */  if (num->n_sign == MINUS) (*out_char) ('-');  /* Output the number. */  if (is_zero (num))    (*out_char) ('0');  else    if (o_base == 10)      {	/* The number is in base 10, do it the fast way. */	nptr = num->n_value;	if (num->n_len > 1 || *nptr != 0)	  for (index=num->n_len; index>0; index--)	    (*out_char) (BCD_CHAR(*nptr++));	else	  nptr++;		/* Now the fraction. */	if (num->n_scale > 0)	  {	    (*out_char) ('.');	    for (index=0; index<num->n_scale; index++)	      (*out_char) (BCD_CHAR(*nptr++));	  }      }    else      {	/* The number is some other base. */	digits = NULL;	init_num (&int_part);	bc_divide (num, _one_, &int_part, 0);	init_num (&frac_part);	init_num (&cur_dig);	init_num (&base);	bc_sub (num, int_part, &frac_part);	int2num (&base, o_base);	init_num (&max_o_digit);	int2num (&max_o_digit, o_base-1);	/* Get the digits of the integer part and push them on a stack. */	while (!is_zero (int_part))	  {	    bc_modulo (int_part, base, &cur_dig, 0);	    temp = (stk_rec *) malloc (sizeof(stk_rec));	    if (temp == NULL) out_of_memory();	    temp->digit = num2long (cur_dig);	    temp->next = digits;	    digits = temp;	    bc_divide (int_part, base, &int_part, 0);	  }	/* Print the digits on the stack. */	if (digits != NULL)	  {	    /* Output the digits. */	    while (digits != NULL)	      {		temp = digits;		digits = digits->next;		if (o_base <= 16) 		  (*out_char) (ref_str[ (int) temp->digit]);		else		  out_long (temp->digit, max_o_digit->n_len, 1, out_char);		free (temp);	      }	  }	/* Get and print the digits of the fraction part. */	if (num->n_scale > 0)	  {	    (*out_char) ('.');	    pre_space = 0;	    t_num = copy_num (_one_);	    while (t_num->n_len <= num->n_scale) {	      bc_multiply (frac_part, base, &frac_part, num->n_scale);	      fdigit = num2long (frac_part);	      int2num (&int_part, fdigit);	      bc_sub (frac_part, int_part, &frac_part);	      if (o_base <= 16)		(*out_char) (ref_str[fdigit]);	      else {		out_long (fdigit, max_o_digit->n_len, pre_space, out_char);		pre_space = 1;	      }	      bc_multiply (t_num, base, &t_num, 0);	    }	  }    	/* Clean up. */	free_num (&int_part);	free_num (&frac_part);	free_num (&base);	free_num (&cur_dig);      }}#if DEBUG > 0/* Debugging procedures.  Some are just so one can call them from the   debugger.  *//* p_n prints the number NUM in base 10. */voidp_n (num)     bc_num num;{  out_num (num, 10, out_char);  return 0;}/* p_b prints a character array as if it was a string of bcd digits. */voidp_v (name, num, len)     char *name;     unsigned char *num;     int len;{  int i;  printf ("%s=", name);  for (i=0; i<len; i++) printf ("%c",BCD_CHAR(num[i]));  printf ("\n");}/* Convert strings to bc numbers.  Base 10 only.*/voidstr2num (num, str, scale)     bc_num *num;     char *str;     int scale;{  int digits, strscale;  char *ptr, *nptr;  char zero_int;  /* Prepare num. */  free_num (num);  /* Check for valid number and count digits. */  ptr = str;  digits = 0;  strscale = 0;  zero_int = FALSE;  if ( (*ptr == '+') || (*ptr == '-'))  ptr++;  /* Sign */  while (*ptr == '0') ptr++;			/* Skip leading zeros. */  while (isdigit(*ptr)) ptr++, digits++;	/* digits */  if (*ptr == '.') ptr++;			/* decimal point */  while (isdigit(*ptr)) ptr++, strscale++;	/* digits */  if ((*ptr != '\0') || (digits+strscale == 0))    {      *num = copy_num (_zero_);      return;    }  /* Adjust numbers and allocate storage and initialize fields. */  strscale = MIN(strscale, scale);  if (digits == 0)    {      zero_int = TRUE;      digits = 1;    }  *num = new_num (digits, strscale);  /* Build the whole number. */  ptr = str;  if (*ptr == '-')    {      (*num)->n_sign = MINUS;      ptr++;    }  else    {      (*num)->n_sign = PLUS;      if (*ptr == '+') ptr++;    }  while (*ptr == '0') ptr++;			/* Skip leading zeros. */  nptr = (*num)->n_value;  if (zero_int)    {      *nptr++ = 0;      digits = 0;    }  for (;digits > 0; digits--)    *nptr++ = CH_VAL(*ptr++);    /* Build the fractional part. */  if (strscale > 0)    {      ptr++;  /* skip the decimal point! */      for (;strscale > 0; strscale--)	*nptr++ = CH_VAL(*ptr++);    }}/* Convert a numbers to a string.  Base 10 only.*/char*num2str (num)      bc_num num;{  char *str, *sptr;  char *nptr;  int  index, signch;  /* Allocate the string memory. */  signch = ( num->n_sign == PLUS ? 0 : 1 );  /* Number of sign chars. */  if (num->n_scale > 0)    str = (char *) malloc (num->n_len + num->n_scale + 2 + signch);  else    str = (char *) malloc (num->n_len + 1 + signch);  if (str == NULL) out_of_memory();  /* The negative sign if needed. */  sptr = str;  if (signch) *sptr++ = '-';  /* Load the whole number. */  nptr = num->n_value;  for (index=num->n_len; index>0; index--)    *sptr++ = BCD_CHAR(*nptr++);  /* Now the fraction. */  if (num->n_scale > 0)    {      *sptr++ = '.';      for (index=0; index<num->n_scale; index++)	*sptr++ = BCD_CHAR(*nptr++);    }  /* Terminate the string and return it! */  *sptr = '\0';  return (str);}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -