# 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`
# ~~~
# 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`
# ~~~
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