def _format_float(self, w_float): """helper for format_float""" space = self.space flags = 0 default_precision = 6 if self._alternate: flags |= rfloat.DTSF_ALT tp = self._type self._get_locale(tp) if tp == "\0": flags |= rfloat.DTSF_ADD_DOT_0 tp = "r" default_precision = 0 elif tp == "n": tp = "g" value = space.float_w(w_float) if tp == "%": tp = "f" value *= 100 add_pct = True else: add_pct = False if self._precision == -1: self._precision = default_precision elif tp == "r": tp = "g" result, special = rfloat.double_to_string(value, tp, self._precision, flags) if add_pct: result += "%" n_digits = len(result) if result[0] == "-": sign = "-" to_number = 1 n_digits -= 1 else: sign = "\0" to_number = 0 have_dec_point, to_remainder = self._parse_number( result, to_number) n_remainder = len(result) - to_remainder if self.is_unicode: digits = result.decode("latin-1") else: digits = result spec = self._calc_num_width(0, sign, to_number, n_digits, n_remainder, have_dec_point, digits) fill = self._fill_char return self.space.wrap( self._fill_number(spec, digits, to_number, 0, fill, to_remainder, False))
def _format_float(self, w_float): """helper for format_float""" space = self.space flags = 0 default_precision = 6 if self._alternate: flags |= rfloat.DTSF_ALT tp = self._type self._get_locale(tp) if tp == "\0": flags |= rfloat.DTSF_ADD_DOT_0 tp = "r" default_precision = 0 elif tp == "n": tp = "g" value = space.float_w(w_float) if tp == "%": tp = "f" value *= 100 add_pct = True else: add_pct = False if self._precision == -1: self._precision = default_precision elif tp == "r": tp = "g" result, special = rfloat.double_to_string(value, tp, self._precision, flags) if add_pct: result += "%" n_digits = len(result) if result[0] == "-": sign = "-" to_number = 1 n_digits -= 1 else: sign = "\0" to_number = 0 have_dec_point, to_remainder = self._parse_number(result, to_number) n_remainder = len(result) - to_remainder if self.is_unicode: digits = result.decode("latin-1") else: digits = result spec = self._calc_num_width(0, sign, to_number, n_digits, n_remainder, have_dec_point, digits) fill = self._fill_char return self.space.wrap(self._fill_number(spec, digits, to_number, 0, fill, to_remainder, False))
def PyOS_double_to_string(space, val, format_code, precision, flags, ptype): """Convert a double val to a string using supplied format_code, precision, and flags. format_code must be one of 'e', 'E', 'f', 'F', 'g', 'G' or 'r'. For 'r', the supplied precision must be 0 and is ignored. The 'r' format code specifies the standard repr() format. flags can be zero or more of the values Py_DTSF_SIGN, Py_DTSF_ADD_DOT_0, or Py_DTSF_ALT, or-ed together: Py_DTSF_SIGN means to always precede the returned string with a sign character, even if val is non-negative. Py_DTSF_ADD_DOT_0 means to ensure that the returned string will not look like an integer. Py_DTSF_ALT means to apply "alternate" formatting rules. See the documentation for the PyOS_snprintf() '#' specifier for details. If ptype is non-NULL, then the value it points to will be set to one of Py_DTST_FINITE, Py_DTST_INFINITE, or Py_DTST_NAN, signifying that val is a finite number, an infinite number, or not a number, respectively. The return value is a pointer to buffer with the converted string or NULL if the conversion failed. The caller is responsible for freeing the returned string by calling PyMem_Free(). """ buffer, rtype = rfloat.double_to_string(val, format_code, intmask(precision), intmask(flags)) if ptype != lltype.nullptr(rffi.INTP.TO): ptype[0] = rffi.cast(rffi.INT, DOUBLE_TO_STRING_TYPES_MAP[rtype]) bufp = rffi.str2charp(buffer) return bufp
def PyOS_double_to_string(space, val, format_code, precision, flags, ptype): """Convert a double val to a string using supplied format_code, precision, and flags. format_code must be one of 'e', 'E', 'f', 'F', 'g', 'G' or 'r'. For 'r', the supplied precision must be 0 and is ignored. The 'r' format code specifies the standard repr() format. flags can be zero or more of the values Py_DTSF_SIGN, Py_DTSF_ADD_DOT_0, or Py_DTSF_ALT, or-ed together: Py_DTSF_SIGN means to always precede the returned string with a sign character, even if val is non-negative. Py_DTSF_ADD_DOT_0 means to ensure that the returned string will not look like an integer. Py_DTSF_ALT means to apply "alternate" formatting rules. See the documentation for the PyOS_snprintf() '#' specifier for details. If ptype is non-NULL, then the value it points to will be set to one of Py_DTST_FINITE, Py_DTST_INFINITE, or Py_DTST_NAN, signifying that val is a finite number, an infinite number, or not a number, respectively. The return value is a pointer to buffer with the converted string or NULL if the conversion failed. The caller is responsible for freeing the returned string by calling PyMem_Free(). """ buffer, rtype = rfloat.double_to_string(val, format_code, intmask(precision), intmask(flags)) if ptype != lltype.nullptr(INTP_real.TO): ptype[0] = rffi.cast(rffi.INT_real, DOUBLE_TO_STRING_TYPES_MAP[rtype]) bufp = rffi.str2charp(buffer) return bufp
def _repr(self, prec=14): _str, _ = double_to_string(self.floatval, "G", prec, DTSF_CUT_EXP_0) if 'E' in _str and '.' not in _str: a, b = _str.split('E') return a + '.0E' + b return _str
def _format_complex(self, w_complex): flags = 0 space = self.space tp = self._type self._get_locale(tp) default_precision = 6 if self._align == "=": # '=' alignment is invalid raise oefmt(space.w_ValueError, "'=' alignment flag is not allowed in complex " "format specifier") if self._fill_char == "0": # zero padding is invalid raise oefmt(space.w_ValueError, "Zero padding is not allowed in complex format " "specifier") if self._alternate: flags |= rfloat.DTSF_ALT skip_re = 0 add_parens = 0 if tp == "\0": #should mirror str() output tp = "g" default_precision = 12 #test if real part is non-zero if (w_complex.realval == 0 and math.copysign(1., w_complex.realval) == 1.): skip_re = 1 else: add_parens = 1 if tp == "n": #same as 'g' except for locale, taken care of later tp = "g" #check if precision not set if self._precision == -1: self._precision = default_precision #in CPython it's named 're' - clashes with re module re_num, special = rfloat.double_to_string(w_complex.realval, tp, self._precision, flags) im_num, special = rfloat.double_to_string(w_complex.imagval, tp, self._precision, flags) n_re_digits = len(re_num) n_im_digits = len(im_num) to_real_number = 0 to_imag_number = 0 re_sign = im_sign = '' #if a sign character is in the output, remember it and skip if re_num[0] == "-": re_sign = "-" to_real_number = 1 n_re_digits -= 1 if im_num[0] == "-": im_sign = "-" to_imag_number = 1 n_im_digits -= 1 #turn off padding - do it after number composition #calc_num_width uses self._width, so assign to temporary variable, #calculate width of real and imag parts, then reassign padding, align tmp_fill_char = self._fill_char tmp_align = self._align tmp_width = self._width self._fill_char = "\0" self._align = "<" self._width = -1 #determine if we have remainder, might include dec or exponent or both re_have_dec, re_remainder_ptr = self._parse_number(re_num, to_real_number) im_have_dec, im_remainder_ptr = self._parse_number(im_num, to_imag_number) if self.is_unicode: re_num = rutf8.decode_latin_1(re_num) im_num = rutf8.decode_latin_1(im_num) #set remainder, in CPython _parse_number sets this #using n_re_digits causes tests to fail re_n_remainder = len(re_num) - re_remainder_ptr im_n_remainder = len(im_num) - im_remainder_ptr re_spec = self._calc_num_width(0, re_sign, to_real_number, n_re_digits, re_n_remainder, re_have_dec, re_num) #capture grouped digits b/c _fill_number reads from self._grouped_digits #self._grouped_digits will get overwritten in imaginary calc_num_width re_grouped_digits = self._grouped_digits if not skip_re: self._sign = "+" im_spec = self._calc_num_width(0, im_sign, to_imag_number, n_im_digits, im_n_remainder, im_have_dec, im_num) im_grouped_digits = self._grouped_digits if skip_re: re_spec.n_total = 0 #reassign width, alignment, fill character self._align = tmp_align self._width = tmp_width self._fill_char = tmp_fill_char #compute L and R padding - stored in self._left_pad and self._right_pad self._calc_padding("", re_spec.n_total + im_spec.n_total + 1 + add_parens * 2) out = self._builder() fill = self._fill_char #compose the string #add left padding out.append_multiple_char(fill, self._left_pad) if add_parens: out.append(self._lit('(')[0]) #if the no. has a real component, add it if not skip_re: out.append(self._fill_number(re_spec, re_num, to_real_number, 0, fill, re_remainder_ptr, False, re_grouped_digits)) #add imaginary component out.append(self._fill_number(im_spec, im_num, to_imag_number, 0, fill, im_remainder_ptr, False, im_grouped_digits)) #add 'j' character out.append(self._lit('j')[0]) if add_parens: out.append(self._lit(')')[0]) #add right padding out.append_multiple_char(fill, self._right_pad) return self.wrap(out.build())
def get_as_string(self): string, _ = double_to_string(self.value, 'G', 12, flags=0) return string
def _format_complex(self, w_complex): flags = 0 space = self.space tp = self._type self._get_locale(tp) default_precision = 6 if self._align == "=": # '=' alignment is invalid msg = ("'=' alignment flag is not allowed in" " complex format specifier") raise OperationError(space.w_ValueError, space.wrap(msg)) if self._fill_char == "0": #zero padding is invalid msg = "Zero padding is not allowed in complex format specifier" raise OperationError(space.w_ValueError, space.wrap(msg)) if self._alternate: flags |= rfloat.DTSF_ALT skip_re = 0 add_parens = 0 if tp == "\0": #should mirror str() output tp = "g" default_precision = 12 #test if real part is non-zero if (w_complex.realval == 0 and copysign(1., w_complex.realval) == 1.): skip_re = 1 else: add_parens = 1 if tp == "n": #same as 'g' except for locale, taken care of later tp = "g" #check if precision not set if self._precision == -1: self._precision = default_precision #in CPython it's named 're' - clashes with re module re_num, special = rfloat.double_to_string(w_complex.realval, tp, self._precision, flags) im_num, special = rfloat.double_to_string(w_complex.imagval, tp, self._precision, flags) n_re_digits = len(re_num) n_im_digits = len(im_num) to_real_number = 0 to_imag_number = 0 re_sign = im_sign = '' #if a sign character is in the output, remember it and skip if re_num[0] == "-": re_sign = "-" to_real_number = 1 n_re_digits -= 1 if im_num[0] == "-": im_sign = "-" to_imag_number = 1 n_im_digits -= 1 #turn off padding - do it after number composition #calc_num_width uses self._width, so assign to temporary variable, #calculate width of real and imag parts, then reassign padding, align tmp_fill_char = self._fill_char tmp_align = self._align tmp_width = self._width self._fill_char = "\0" self._align = "<" self._width = -1 #determine if we have remainder, might include dec or exponent or both re_have_dec, re_remainder_ptr = self._parse_number(re_num, to_real_number) im_have_dec, im_remainder_ptr = self._parse_number(im_num, to_imag_number) if self.is_unicode: re_num = re_num.decode("latin-1") im_num = im_num.decode("latin-1") #set remainder, in CPython _parse_number sets this #using n_re_digits causes tests to fail re_n_remainder = len(re_num) - re_remainder_ptr im_n_remainder = len(im_num) - im_remainder_ptr re_spec = self._calc_num_width(0, re_sign, to_real_number, n_re_digits, re_n_remainder, re_have_dec, re_num) #capture grouped digits b/c _fill_number reads from self._grouped_digits #self._grouped_digits will get overwritten in imaginary calc_num_width re_grouped_digits = self._grouped_digits if not skip_re: self._sign = "+" im_spec = self._calc_num_width(0, im_sign, to_imag_number, n_im_digits, im_n_remainder, im_have_dec, im_num) im_grouped_digits = self._grouped_digits if skip_re: re_spec.n_total = 0 #reassign width, alignment, fill character self._align = tmp_align self._width = tmp_width self._fill_char = tmp_fill_char #compute L and R padding - stored in self._left_pad and self._right_pad self._calc_padding(self.empty, re_spec.n_total + im_spec.n_total + 1 + add_parens * 2) out = self._builder() fill = self._fill_char #compose the string #add left padding out.append_multiple_char(fill, self._left_pad) if add_parens: out.append(self._lit('(')[0]) #if the no. has a real component, add it if not skip_re: out.append(self._fill_number(re_spec, re_num, to_real_number, 0, fill, re_remainder_ptr, False, re_grouped_digits)) #add imaginary component out.append(self._fill_number(im_spec, im_num, to_imag_number, 0, fill, im_remainder_ptr, False, im_grouped_digits)) #add 'j' character out.append(self._lit('j')[0]) if add_parens: out.append(self._lit(')')[0]) #add right padding out.append_multiple_char(fill, self._right_pad) return self.space.wrap(out.build())