[Python-checkins] r71190 - python/branches/py3k-short-float-repr/Python/pystrtod.c
mark.dickinson
python-checkins at python.org
Sat Apr 4 22:47:27 CEST 2009
Author: mark.dickinson
Date: Sat Apr 4 22:47:26 2009
New Revision: 71190
Log:
Simplify some logic in format_float_short and PyOS_double_to_string:
- min_digits keeps track of minimum number of digits needed
- no need to add .0 explicitly at the end; it should be already
there if we set min_digits appropriately. Remove is_integer logic.
- n_wanted_digits_after_decimal is unused.
Modified:
python/branches/py3k-short-float-repr/Python/pystrtod.c
Modified: python/branches/py3k-short-float-repr/Python/pystrtod.c
==============================================================================
--- python/branches/py3k-short-float-repr/Python/pystrtod.c (original)
+++ python/branches/py3k-short-float-repr/Python/pystrtod.c Sat Apr 4 22:47:26 2009
@@ -519,22 +519,34 @@
};
-/* Convert a Python float to a minimal string that evaluates back to that
- float. The output is minimal in the sense of having the fewest possible
- number of significant digits. */
+/* Convert a double d to a string, and put the result into the buffer buf.
+
+ Arguments:
+ buflen is the length of the provided buffer
+ d is the double to be converted
+ format_code is one of 'e', 'f', 'g', 'r' or 's'. 'e', 'f' and 'g'
+ correspond to '%e', '%f' and '%g'; 'r' and 's' correspond
+ to repr and str.
+ mode is one of '0', '2' or '3', and is completely determined by
+ format_code: 'e', 'g' and 's' use mode 2; 'f' mode 3, 'r' mode 0.
+ precision is the desired precision
+ always_add_sign is nonzero if a '+' sign should be included for positive
+ numbers
+ add_dot_0_if_integer is nonzero if integers in non-exponential form
+ should have ".0" added. Only applies to format codes 'r' and 's'.
+ use_alt_formatting is nonzero if alternative formatting should be
+ used. Only applies to format codes 'e', 'f' and 'g'.
+ */
static void
format_float_short(char *buf, Py_ssize_t buflen, double d, char format_code,
int mode, Py_ssize_t precision,
- Py_ssize_t n_wanted_digits_after_decimal,
int always_add_sign, int add_dot_0_if_integer,
int use_alt_formatting, char **float_strings)
{
char *digits, *digits_end;
- int decpt, sign, exp_len, dec_pos;
- int use_exp = 0;
- int is_integer; /* is the output produced so far just an integer? */
- Py_ssize_t n_digits, trailing_zeros;
+ int decpt, sign, exp_len, dec_pos, use_exp = 0;
+ Py_ssize_t n_digits, min_digits = 0;
/* precision of 0 makes no sense for 'g' format; interpret as 1 */
if (precision == 0 && format_code == 'g')
@@ -566,10 +578,7 @@
}
else {
/* shouldn't get here: Gay's code should always return
- something starting with a digit, an 'I', or an
- 'N' */
- /*printf("Help! dtoa returned: %.*s\n",
- (int)n_digits, digits);*/
+ something starting with a digit, an 'I', or 'N' */
strncpy(buf, "ERR", 3);
buf += 3;
assert(0);
@@ -585,46 +594,42 @@
type = 'g';
over time, those tests should be deleted
*/
-/* if (decpt > 50 && format_code == 'f')
- format_code = 'g'; */
- /* Detect if we're using exponents or not */
+ /* Detect if we're using exponents or not, and figure out how many
+ additional digits we need beyond those provided by dtoa. */
switch (format_code) {
case 'e':
use_exp = 1;
- trailing_zeros = precision - n_digits;
+ min_digits = precision;
break;
case 'f':
- use_exp = 0;
- trailing_zeros = decpt + precision - n_digits;
+ min_digits = decpt + precision;
break;
case 'g':
- if ((mode != 0) && (decpt > precision || decpt <= -4))
+ if (decpt <= -4 || decpt > precision)
use_exp = 1;
- else {
- use_exp = 0;
- }
if (use_alt_formatting)
- trailing_zeros = precision - n_digits;
- else
- trailing_zeros = 0;
+ min_digits = precision;
break;
case 'r':
- /* use exponent for values >= 1e16 or < 1e-4 */
- if ((-4 < decpt) && (decpt <= 16))
- use_exp = 0;
- else
+ if (decpt <= -4 || decpt > 16)
use_exp = 1;
- trailing_zeros = 0;
+ else if (add_dot_0_if_integer)
+ min_digits = decpt + 1;
break;
case 's':
- /* str: use exponent for values >= 1e11 or < 1e-4 */
- if (-4 < decpt && decpt < precision)
- use_exp = 0;
- else
+ /* if we're forcing a digit after the point, convert to
+ exponential format at 1e11. If not, convert at 1e12. */
+ if (decpt <= -4 ||
+ decpt > precision - (add_dot_0_if_integer != 0))
use_exp = 1;
- trailing_zeros = 0;
+ else if (add_dot_0_if_integer)
+ min_digits = decpt + 1;
break;
+ default:
+ PyErr_BadInternalCall();
+ *buf = '\0';
+ return;
}
/* Always add a negative sign, and a plus sign if always_add_sign. */
@@ -659,42 +664,31 @@
strncpy(buf, digits, n_digits);
buf += n_digits;
}
+ min_digits -= n_digits;
+
/* and zeros on the right up to the decimal point */
if (n_digits < dec_pos) {
memset(buf, '0', dec_pos-n_digits);
buf += dec_pos-n_digits;
*buf++ = '.';
- trailing_zeros -= dec_pos-n_digits;
+ min_digits -= dec_pos-n_digits;
}
- /* and more trailing zeros, when necessary */
- if (trailing_zeros > 0) {
- memset(buf, '0', trailing_zeros);
- buf += trailing_zeros;
+
+ /* and more trailing zeros when necessary */
+ if (min_digits > 0) {
+ memset(buf, '0', min_digits);
+ buf += min_digits;
}
- /* If we're at a trailing decimal, delete it. We are then just an
- integer. */
- if (buf[-1] == '.' && !use_alt_formatting) {
+ /* delete a trailing decimal pt unless using alternative formatting. */
+ if (buf[-1] == '.' && !use_alt_formatting)
buf--;
- is_integer = 1;
- }
- else
- /* The decimal isn't at the end, so it's somewhere else in the
- string. We are therefore not an integer. */
- is_integer = 0;
/* Now that we've done zero padding, add an exponent if needed. */
if (use_exp) {
*buf++ = float_strings[OFS_E][0];
exp_len = sprintf(buf, "%+.02d", decpt-1);
buf += exp_len;
- is_integer = 0;
- }
-
- /* Add ".0" if we're an integer? */
- if (add_dot_0_if_integer && is_integer) {
- *buf++ = '.';
- *buf++ = '0';
}
*buf++ = '\0';
@@ -709,7 +703,6 @@
char* buf = (char *)PyMem_Malloc(512);
char lc_format_code = format_code;
char** float_strings = lc_float_strings;
- Py_ssize_t n_wanted_digits_after_decimal = precision;
int mode = 0;
/* Validate format_code, and map upper and lower case */
@@ -749,8 +742,6 @@
break;
case 'g':
mode = 2;
- if (flags & Py_DTSF_ALT)
- n_wanted_digits_after_decimal--;
break;
case 'r':
/* "repr" pseudo-mode */
@@ -767,7 +758,7 @@
/* XXX validate format_code */
format_float_short(buf, 512, val, lc_format_code, mode, precision,
- n_wanted_digits_after_decimal, flags & Py_DTSF_SIGN,
+ flags & Py_DTSF_SIGN,
flags & Py_DTSF_ADD_DOT_0, flags & Py_DTSF_ALT,
float_strings);
More information about the Python-checkins
mailing list