Open JeffreySarnoff opened 2 years ago
What does _
have to do with anything here? Int literals with large values parse as BigInt
but floats to not.
julia> 123456789_123456789_123456789_123456789.123456789_12345678 |> typeof
Float64
julia> 123456789123456789123456789123456789.12345678912345678 |> typeof
Float64
There's also the big""
string macro, which does handle both of these:
julia> big"123456789_123456789_123456789_123456789_123456789"
123456789123456789123456789123456789123456789
julia> ans |> typeof
BigInt
julia> big"123456789_123456789_123456789_123456789.123456789_12345678"
1.234567891234567891234567891234567891234567891234567799999999999999999999999999e+35
julia> ans |> typeof
BigFloat
"Int literals with many digits parse as BigInt but float literals with many digits do not."
It would be simpler for users if both int and float literals with many digits parsed accordingly
I still do see the advantage of letting BigFloat(str)
yet not letting BigInt(str)
function as a constructor.
Early in the design of Julia, support for interposing neutral '_'s within digit sequences,
to make long numbers easier to read and simpler to comparison check,
was discussed, decided, adopted and provided.
Today, this capability exists throughout most of the ways of using Julia.
The example shows an uncovered situation.
Wherever an extended precision number that intersperses underscores is become non-workable,
that's a place that ought be made workable. That there are alternatives e.g big"_" seems more a band-aid
than an elegant solution to people who use Julia and regularly work with values specified by 100 digits or more.
@Seelengrab yes -- I had forgotten that big
also is a string macro
Today, this capability exists throughout most of the ways of using Julia. The example shows an uncovered situation.
I still don't understand. What is the "uncovered situation"? Your example is:
abigint = 123456789_123456789_123456789_123456789_123456789
typeof(abigint) == BigInt
abigfloat = 123456789_123456789_123456789_123456789.123456789_12345678
typeof(abigfloat) == Float64
but this is true even if you remove the _
. So what change does _
make to anything? Please speak in as simple language as you can because someone as me who is a non-native speaker might have difficulties understanding otherwise :)
What is the "uncovered situation"?
If I understand correctly, the "uncovered situation" regarding underscores is that they are only allowed in literals, not in strings that are parsed to a number. However, this is not specific to BigFloat
s:
julia> parse(BigFloat, "123.456_789")
ERROR: ArgumentError: cannot parse "123.456_789" as BigFloat
[...]
julia> parse(Float64, "123.456_789")
ERROR: ArgumentError: cannot parse "123.456_789" as Float64
[...]
julia> parse(Int, "123_456")
ERROR: ArgumentError: invalid base 10 digit '_' in "123_456"
[...]
The other part of the issue (the "asymmetry") is that all floating-point literals create Float64
s, even if they have a lot of digits, whereas integer literals with lots of digits create BigInt
s. However, I don’t think it makes much sense to parse floating-point literals with lots of digits as BigFloat
s. The situations for integers and floats are simply different:
Int64
, Int128
is used. And if Int128
is still not enough, the result is a BigInt
.0.1
actually parses to a number that is slightly larger than 1//10
, because Float64
cannot represent the number 1//10
exactly. But 1//10
cannot be exactly represented by a BigFloat
either.Creating a BigFloat
if a floating-point literal contains more than a certain number of digits seems arbitrary. At what number of digits do you switch to BigFloat
? As the number 0.1
demonstrates, even for a literal with just one decimal place, a BigFloat
will be closer to the exact value than a Float64
. Should the literal 0.1
therefore create a BigFloat
? I don’t think so.
@sostock Thank you for explaining and then detailing my notes. @KristofferC You communicate so well in English that I forgot.
There is some more to this -- I need to write code :)
So if it is like @sostock says that the issue is with _
in parse
vs literals then I don't understand the title. The ability of being able to use _
in literals but not in parse
is true for all integer types and is the same for BigInt and BigFloat so how does the title saying claiming that they are "not symmetric" make sense?
@KristofferC IIUC the "asymmetry" is two part:
_
s, so Bigfloats can't be generated with _
s but Bigints can because they can be generated with literalsBut as @Seelengrab pointed out, the big""
macro handles both types with underscores giving a workaround to the second asymmetry.
As @sostock pointed out, curing the first asymmetry is "complicated" like all floating point, and is best handled explicitly using big""
.
It seems asymmetric that
BigInt("") does not do anything, however
to write a BigFloat constant into a source file, the type and a string are needed
Writing numeric constants with many digits in a source file is error-prone without support for underscores. Writing BigInts one way and BigFloats another way to use them in a source file is kinda obtuse,
there is much more efficient way to remove or to ignore the '_'s -- its not something I have had to do