 # Why is big(0.5) printed as 0.50?

I’m not sure if this is the intended behavior:

``````julia> 0.5
0.5

julia> big(0.5)
0.50

julia> big(0.5) == 0.5
true
``````

Why the extra `0` at the end for a `BigFloat`?

Output is done by the show function which is different for the two types:

``````julia> @which show(stdout,big(0.5))
show(io::IO, b::BigFloat) in Base.MPFR at mpfr.jl:1002

julia> @which show(stdout,0.5)
show(io::IO, x::T) where T<:Union{Float16, Float32, Float64} in Base.Ryu at ryu\Ryu.jl:111
``````

This is show for BigFloat:

``````function show(io::IO, b::BigFloat)
if get(io, :compact, false)
print(io, _string(b, 5))
else
print(io, _string(b))
end
end
``````

And this for standard Float64:

``````function Base.show(io::IO, x::T, forceuntyped::Bool=false, fromprint::Bool=false) where {T <: Base.IEEEFloat}
compact = get(io, :compact, false)::Bool
buf = Base.StringVector(neededdigits(T))
typed = !forceuntyped && !compact && get(io, :typeinfo, Any) != typeof(x)
pos = writeshortest(buf, 1, x, false, false, true, -1,
(x isa Float32 && !fromprint) ? UInt8('f') : UInt8('e'), false, UInt8('.'), typed, compact)
write(io, resize!(buf, pos - 1))
return
end
``````

I didn’t checked now for the specific additional `0` in the bigFloat case, but you can play around with both implementations to explore the differences.

1 Like

For the bigFloat you also need (from the same file):

``````function _string(x::BigFloat, fmt::String)::String
isfinite(x) || return string(Float64(x))
_prettify_bigfloat(string_mpfr(x, fmt))
end
_string(x::BigFloat) = _string(x, "%.Re")
_string(x::BigFloat, k::Integer) = _string(x, "%.\$(k)Re")

string(b::BigFloat) = _string(b)

print(io::IO, b::BigFloat) = print(io, string(b))
``````

but you can open those files on your own to get all needed dependencies, like
`_prettify_bigfloat(s::String)::String`

I realize that the methods are different, but my question was if this behavior is intended or if it is a bug in the display format.

3 Likes

I don’t know, probably not intended that there is some special reasoning behind it. But that doesn’t make it a bug. I would say: it’s not important enough to deal with it in a priorized way.

1 Like

The string is rendered by MPFR as “5.0e-1”. Julia gets rid of the “e” notation by moving the decimal point.

6 Likes

For convenience/reference, the code that does that is here:

``````function _prettify_bigfloat(s::String)::String
mantissa, exponent = split(s, 'e')
if !occursin('.', mantissa)
mantissa = string(mantissa, '.')
end
mantissa = rstrip(mantissa, '0')
if endswith(mantissa, '.')
mantissa = string(mantissa, '0')
end
expo = parse(Int, exponent)
if -5 < expo < 6
expo == 0 && return mantissa
int, frac = split(mantissa, '.')
if expo > 0
expo < length(frac) ?
string(int, frac[1:expo], '.', frac[expo+1:end]) :
string(int, frac, '0'^(expo-length(frac)), '.', '0')
else
neg = startswith(int, '-')
neg == true && (int = lstrip(int, '-'))
@assert length(int) == 1
string(neg ? '-' : "", '0', '.', '0'^(-expo-1), int, frac)
end
else
string(mantissa, 'e', exponent)
end
end
``````

From a brief study of this code, it seems like the line

``````string(neg ? '-' : "", '0', '.', '0'^(-expo-1), int, frac)
``````

…could be tweaked to not include `frac` if it is zero, as is the case with 0.5.

Maybe that behavior is there for a reason, but I guess I could submit a PR and see what feedback I get.

5 Likes