Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

@printf aborts with InexactError #37552

Closed
eschnett opened this issue Sep 12, 2020 · 4 comments · Fixed by #37554
Closed

@printf aborts with InexactError #37552

eschnett opened this issue Sep 12, 2020 · 4 comments · Fixed by #37554

Comments

@eschnett
Copy link
Contributor

I am using the current master of Julia. I see this error:

julia> using Printf
julia> @printf("%d", 1.0e100)
ERROR: InexactError: Int64(1.0e100)
Stacktrace:
 [1] Int64
   @ ./float.jl:710 [inlined]
 [2] Integer
   @ ./boot.jl:771 [inlined]
 [3] plength
   @ ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:678 [inlined]
 [4] computelen
   @ ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:692 [inlined]
 [5] format(io::Base.TTY, f::Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'d'}}}}, args::Float64)
   @ Printf ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:718
 [6] top-level scope
   @ REPL[7]:1

I think that @sprintf should not abort with an error when outputting large values.

The problem is that the format %d expect an integer, but the argument 1.0e100 is too large to be converted to an integer when counting digits.

This works:

julia> @printf("%d", big(1.0e100))
10000000000000000159028911097599180468360808563945281389781327557747838772170381060813469985856815104
quinnj added a commit that referenced this issue Sep 13, 2020
Fixes #37552. As pointed out by Jameson, the non-integer conversion code
for the `%d` specifier handling code wasn't super robust; I wasn't sure
how robust it really needed to be, since it seems a bit sketchy to me
for users to be relying on Printf conversion behavior of non-integers
with `%d` anyway; C even throws a really scary warning if you pass
non-integer for `%d`. But anyways, this isn't that much more machinery
and puts back support for printf formatting of `Rational` with `%d`
anyway. But a note to users, I'd strongly suggest doing your own
conversion, `trunc`, `round`, whatever yourself to ensure you fully
understand what's going on if you really need to use the `%d` with
non-integer arguments.

As for the issue reported, it's note quite as severe a use-case since
they're just trying to represent a _huge_ integer via `Float64`, which
seems decently reasonable.
@quinnj
Copy link
Member

quinnj commented Sep 13, 2020

Thanks for reporting; fix is up: #37554

quinnj added a commit that referenced this issue Sep 13, 2020
* More robust non-integer conversions for %d Printf specifier

Fixes #37552. As pointed out by Jameson, the non-integer conversion code
for the `%d` specifier handling code wasn't super robust; I wasn't sure
how robust it really needed to be, since it seems a bit sketchy to me
for users to be relying on Printf conversion behavior of non-integers
with `%d` anyway; C even throws a really scary warning if you pass
non-integer for `%d`. But anyways, this isn't that much more machinery
and puts back support for printf formatting of `Rational` with `%d`
anyway. But a note to users, I'd strongly suggest doing your own
conversion, `trunc`, `round`, whatever yourself to ensure you fully
understand what's going on if you really need to use the `%d` with
non-integer arguments.

As for the issue reported, it's note quite as severe a use-case since
they're just trying to represent a _huge_ integer via `Float64`, which
seems decently reasonable.

* Add test for Rational
@eschnett
Copy link
Contributor Author

A related problem remains with Inf and NaN instead of large numbers:

julia> @printf("%d", Inf)
ERROR: InexactError: BigInt(Inf)
Stacktrace:
 [1] BigInt
   @ ./gmp.jl:298 [inlined]
 [2] toint(x::Float64)
   @ Printf ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:267
 [3] plength(f::Printf.Spec{Val{'d'}}, x::Float64)
   @ Printf ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:684
 [4] computelen
   @ ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:698 [inlined]
 [5] format(io::Base.TTY, f::Printf.Format{Base.CodeUnits{UInt8, String}, Tuple{Printf.Spec{Val{'d'}}}}, args::Float64)
   @ Printf ~/src/julia-master/usr/share/julia/stdlib/v1.6/Printf/src/Printf.jl:724
 [6] top-level scope
   @ REPL[3]:1

@quinnj
Copy link
Member

quinnj commented Sep 14, 2020

Ugh, I hate that we allowed these at all.

@eschnett
Copy link
Contributor Author

You could silently convert %d to %.0f for floating-point arguments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants