X-Git-Url: http://nitlanguage.org diff --git a/lib/core/text/abstract_text.nit b/lib/core/text/abstract_text.nit index 0b2c1ce..1b4b383 100644 --- a/lib/core/text/abstract_text.nit +++ b/lib/core/text/abstract_text.nit @@ -253,6 +253,7 @@ abstract class Text # assert "0x64".to_i == 100 # assert "0b1100_0011".to_i== 195 # assert "--12".to_i == 12 + # assert "+45".to_i == 45 # ~~~ # # REQUIRE: `self`.`is_int` @@ -794,7 +795,7 @@ abstract class Text else if c == ':' or c == ' ' or c == '#' then b.add('\\') b.add(c) - else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' or c == '=' then + else if c.code_point < 32 or c == ';' or c == '|' or c == '\\' then b.append("?{c.code_point.to_base(16)}") else b.add(c) @@ -2028,25 +2029,76 @@ redef class Float # ~~~ # assert 12.34.to_s == "12.34" # assert (-0120.030).to_s == "-120.03" + # assert (-inf).to_s == "-inf" + # assert (nan).to_s == "nan" # ~~~ # # see `to_precision` for a custom precision. redef fun to_s do - var str = to_precision( 3 ) - if is_inf != 0 or is_nan then return str - var len = str.length + var str = to_precision(3) + return adapt_number_of_decimal(str, false) + end + + # Return the representation of `self`, with scientific notation + # + # Adpat the number of decimals as needed from 1 to a maximum of 6 + # ~~~ + # assert 12.34.to_sci == "1.234e+01" + # assert 123.45.to_sci.to_f.to_sci == "1.2345e+02" + # assert 0.001234.to_sci == "1.234e-03" + # assert (inf).to_sci == "inf" + # assert (nan).to_sci == "nan" + # ~~~ + fun to_sci: String + do + var is_inf_or_nan = check_inf_or_nan + if is_inf_or_nan != null then return is_inf_or_nan + return adapt_number_of_decimal(return_from_specific_format("%e".to_cstring), true) + end + + # Return the `string_number` with the adapted number of decimal (i.e the fonction remove the useless `0`) + # `is_expo` it's here to specifi if the given `string_number` is in scientific notation + private fun adapt_number_of_decimal(string_number: String, is_expo: Bool): String + do + # check if `self` does not need an adaptation of the decimal + if is_inf != 0 or is_nan then return string_number + var len = string_number.length + var expo_value = "" + var numeric_value = "" for i in [0..len-1] do - var j = len-1-i - var c = str.chars[j] - if c == '0' then - continue - else if c == '.' then - return str.substring( 0, j+2 ) - else - return str.substring( 0, j+1 ) + var j = len - 1 - i + var c = string_number.chars[j] + if not is_expo then + if c == '0' then + continue + else if c == '.' then + numeric_value = string_number.substring( 0, j + 2) + break + else + numeric_value = string_number.substring( 0, j + 1) + break + end + else if c == 'e' then + expo_value = string_number.substring( j, len - 1 ) + is_expo = false end end - return str + return numeric_value + expo_value + end + + # Return a string representation of `self` in fonction if it is not a number or infinity. + # Return `null` if `self` is not a not a number or an infinity + private fun check_inf_or_nan: nullable String + do + if is_nan then return "nan" + + var isinf = self.is_inf + if isinf == 1 then + return "inf" + else if isinf == -1 then + return "-inf" + end + return null end # `String` representation of `self` with the given number of `decimals` @@ -2061,31 +2113,39 @@ redef class Float # ~~~ fun to_precision(decimals: Int): String do - if is_nan then return "nan" + var is_inf_or_nan = check_inf_or_nan + if is_inf_or_nan != null then return is_inf_or_nan + return return_from_specific_format("%.{decimals}f".to_cstring) + end - var isinf = self.is_inf - if isinf == 1 then - return "inf" - else if isinf == -1 then - return "-inf" - end + # Returns the hexadecimal (`String`) representation of `self` in exponential notation + # + # ~~~ + # assert 12.345.to_hexa_exponential_notation == "0x1.8b0a3d70a3d71p+3" + # assert 12.345.to_hexa_exponential_notation.to_f == 12.345 + # ~~~ + fun to_hexa_exponential_notation: String + do + return return_from_specific_format("%a".to_cstring) + end - var size = to_precision_size(decimals) - var cstr = new CString(size+1) - to_precision_fill(decimals, size+1, cstr) - return cstr.to_s_unsafe(byte_length=size, copy=false) + # Return the representation of `self`, with the specific given c `format`. + private fun return_from_specific_format(format: CString): String + do + var size = to_precision_size_with_format(format) + var cstr = new CString(size + 1) + to_precision_fill_with_format(format, size + 1, cstr) + return cstr.to_s_unsafe(byte_length = size, copy = false) end - # Required string length to hold `self` with `nb` decimals - # - # The length does not include the terminating null byte. - private fun to_precision_size(nb: Int): Int `{ - return snprintf(NULL, 0, "%.*f", (int)nb, self); + # The lenght of `self` in the specific given c `format` + private fun to_precision_size_with_format(format: CString): Int`{ + return snprintf(NULL, 0, format, self); `} - # Fill `cstr` with `self` and `nb` decimals - private fun to_precision_fill(nb, size: Int, cstr: CString) `{ - snprintf(cstr, size, "%.*f", (int)nb, self); + # Fill `cstr` with `self` in the specific given c `format` + private fun to_precision_fill_with_format(format: CString, size: Int, cstr: CString) `{ + snprintf(cstr, size, format, self); `} end