📄 atof-generic.c
字号:
precision = (address_of_generic_floating_point_number -> high - address_of_generic_floating_point_number -> low + 1 ); /* Number of destination littlenums. */ /* Includes guard bits (two littlenums worth) */ maximum_useful_digits = ( ((double) (precision - 2)) * ((double) (LITTLENUM_NUMBER_OF_BITS)) / (LOG_TO_BASE_2_OF_10) ) + 2; /* 2 :: guard digits. */ if (number_of_digits_available > maximum_useful_digits) { number_of_digits_to_use = maximum_useful_digits; } else { number_of_digits_to_use = number_of_digits_available; } decimal_exponent += number_of_digits_before_decimal - number_of_digits_to_use; more_than_enough_bits_for_digits = ((((double)number_of_digits_to_use) * LOG_TO_BASE_2_OF_10) + 1); more_than_enough_littlenums_for_digits = ( more_than_enough_bits_for_digits / LITTLENUM_NUMBER_OF_BITS ) + 2; /* * Compute (digits) part. In "12.34E56" this is the "1234" part. * Arithmetic is exact here. If no digits are supplied then * this part is a 0 valued binary integer. * Allocate room to build up the binary number as littlenums. * We want this memory to disappear when we leave this function. * Assume no alignment problems => (room for n objects) == * n * (room for 1 object). */ size_of_digits_in_littlenums = more_than_enough_littlenums_for_digits; size_of_digits_in_chars = size_of_digits_in_littlenums * sizeof( LITTLENUM_TYPE ); digits_binary_low = (LITTLENUM_TYPE *) alloca (size_of_digits_in_chars); bzero ((char *)digits_binary_low, size_of_digits_in_chars); /* Digits_binary_low[] is allocated and zeroed. */ { /* * Parse the decimal digits as if * digits_low was in the units position. * Emit a binary number into digits_binary_low[]. * * Use a large-precision version of: * (((1st-digit) * 10 + 2nd-digit) * 10 + 3rd-digit ...) * 10 + last-digit */ char * p; char c; int count; /* Number of useful digits left to scan. */ for (p = first_digit, count = number_of_digits_to_use; count; p ++, -- count) { c = * p; if (isdigit(c)) { /* * Multiply by 10. Assume can never overflow. * Add this digit to digits_binary_low[]. */ long int carry; LITTLENUM_TYPE * littlenum_pointer; LITTLENUM_TYPE * littlenum_limit; littlenum_limit = digits_binary_low + more_than_enough_littlenums_for_digits - 1; carry = c - '0'; /* char -> binary */ for (littlenum_pointer = digits_binary_low; littlenum_pointer <= littlenum_limit; littlenum_pointer ++) { long int work; work = carry + 10 * (long)(*littlenum_pointer); * littlenum_pointer = work & LITTLENUM_MASK; carry = work >> LITTLENUM_NUMBER_OF_BITS; } if (carry != 0) { /* * We have a GROSS internal error. * This should never happen. */ abort(); /* RMS prefers abort() to any message. */ } } else { ++ count; /* '.' doesn't alter digits used count. */ } /* if valid digit */ } /* for each digit */ } /* * Digits_binary_low[] properly encodes the value of the digits. * Forget about any high-order littlenums that are 0. */ while (digits_binary_low [size_of_digits_in_littlenums - 1] == 0 && size_of_digits_in_littlenums >= 2) size_of_digits_in_littlenums --; digits_flonum . low = digits_binary_low; digits_flonum . high = digits_binary_low + size_of_digits_in_littlenums - 1; digits_flonum . leader = digits_flonum . high; digits_flonum . exponent = 0; /* * The value of digits_flonum . sign should not be important. * We have already decided the output's sign. * We trust that the sign won't influence the other parts of the number! * So we give it a value for these reasons: * (1) courtesy to humans reading/debugging * these numbers so they don't get excited about strange values * (2) in future there may be more meaning attached to sign, * and what was * harmless noise may become disruptive, ill-conditioned (or worse) * input. */ digits_flonum . sign = '+'; { /* * Compute the mantssa (& exponent) of the power of 10. * If sucessful, then multiply the power of 10 by the digits * giving return_binary_mantissa and return_binary_exponent. */ LITTLENUM_TYPE *power_binary_low; int decimal_exponent_is_negative; /* This refers to the "-56" in "12.34E-56". */ /* FALSE: decimal_exponent is positive (or 0) */ /* TRUE: decimal_exponent is negative */ FLONUM_TYPE temporary_flonum; LITTLENUM_TYPE *temporary_binary_low; int size_of_power_in_littlenums; int size_of_power_in_chars; size_of_power_in_littlenums = precision;/* Precision has a built-in fudge factor so we get a few guard bits. */ decimal_exponent_is_negative = decimal_exponent < 0; if (decimal_exponent_is_negative) { decimal_exponent = - decimal_exponent; } /* From now on: the decimal exponent is > 0. Its sign is seperate. */ size_of_power_in_chars = size_of_power_in_littlenums * sizeof( LITTLENUM_TYPE ) + 2; power_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars ); temporary_binary_low = (LITTLENUM_TYPE *) alloca ( size_of_power_in_chars ); bzero ((char *)power_binary_low, size_of_power_in_chars); * power_binary_low = 1; power_of_10_flonum . exponent = 0; power_of_10_flonum . low = power_binary_low; power_of_10_flonum . leader = power_binary_low; power_of_10_flonum . high = power_binary_low + size_of_power_in_littlenums - 1; power_of_10_flonum . sign = '+'; temporary_flonum . low = temporary_binary_low; temporary_flonum . high = temporary_binary_low + size_of_power_in_littlenums - 1; /* * (power) == 1. * Space for temporary_flonum allocated. */ /* * ... * * WHILE more bits * DO find next bit (with place value) * multiply into power mantissa * OD */ { int place_number_limit; /* Any 10^(2^n) whose "n" exceeds this */ /* value will fall off the end of */ /* flonum_XXXX_powers_of_ten[]. */ int place_number; const FLONUM_TYPE * multiplicand; /* -> 10^(2^n) */ place_number_limit = table_size_of_flonum_powers_of_ten; multiplicand = ( decimal_exponent_is_negative ? flonum_negative_powers_of_ten : flonum_positive_powers_of_ten); for (place_number = 1; /* Place value of this bit of exponent. */ decimal_exponent; /* Quit when no more 1 bits in exponent. */ decimal_exponent >>= 1 , place_number ++) { if (decimal_exponent & 1) { if (place_number > place_number_limit) { /* * The decimal exponent has a magnitude so great that * our tables can't help us fragment it. Although this * routine is in error because it can't imagine a * number that big, signal an error as if it is the * user's fault for presenting such a big number. */ return_value = ERROR_EXPONENT_OVERFLOW; /* * quit out of loop gracefully */ decimal_exponent = 0; } else {#ifdef TRACEprintf("before multiply, place_number = %d., power_of_10_flonum:\n", place_number);flonum_print( & power_of_10_flonum );(void)putchar('\n');#endif flonum_multip (multiplicand + place_number, & power_of_10_flonum, & temporary_flonum); flonum_copy (& temporary_flonum, & power_of_10_flonum); } /* If this bit of decimal_exponent was computable.*/ } /* If this bit of decimal_exponent was set. */ } /* For each bit of binary representation of exponent */#ifdef TRACEprintf( " after computing power_of_10_flonum: " );flonum_print( & power_of_10_flonum );(void)putchar('\n');#endif } } /* * power_of_10_flonum is power of ten in binary (mantissa) , (exponent). * It may be the number 1, in which case we don't NEED to multiply. * * Multiply (decimal digits) by power_of_10_flonum. */ flonum_multip (& power_of_10_flonum, & digits_flonum, address_of_generic_floating_point_number); /* Assert sign of the number we made is '+'. */ address_of_generic_floating_point_number -> sign = digits_sign_char; } /* If we had any significant digits. */ return (return_value);} /* atof_generic () *//* end: atof_generic.c */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -