It depends on what you mean by “the” base-10 mantissa and exponent. I assume you are mainly interested in binary floating-point types like Float64 and Float32.
The one that is shown in the default printed representation of a Float64 is only an approximation — it is the shortest decimal representation that rounds to the same Float64 value. If this is what you want, I’m not aware of a documented API other than parsing the printed representation. If you are willing to use an undocumented API, there is mantissa, exponent = Base.Ryu.reduce_shortest(x).
Of course, there is an exact decimal representation too, but it typically requires a large number of digits.
Is this the result you expected? Based on the title, I would have expected mantissa 317 and exponent -2 (or an equivalent alternative like 3170 and -3) because 317 * 10^-2 = 3.17.
Coincidentally, I work on JuliaMath/Decimals.jl these days. You could use that package to parse a number and get the mantissa and exponent from the resulting Decimal:
using Decimals
x = parse(Decimal, "3.17")
mantissa = x.c # 317
exponent = x.q # -2
The package has some bugs (parsing has been fixed recently in a pending PR), but I am trying to improve it and it might already be sufficient for your case now.
Technically you are right, but I am after a string which I can just cut off at some point and insert a decimal dot, so I am flexible.
The point of the exercise is for printing, into LaTeX. That is, I want to generate output like raw"$4.92 \cdot 10^{-3}$" and raw"$22.71 \cdot 10^{6}$" (engineering notation).
Doing something with a numeric log is highly likely to have catastrophic rounding problems around powers of 10.
In my view, the best answer in this case is to use standard tooling (like @sprintf) and fix it up as strings — either as a split like Tamas first suggested or with a regex. Both are really fine.
The problem I was worried about isn’t small errors. I suspect that it’s possible the exponent and mantissa might round different ways. Around powers of 10 that could easily lead to a factor of 10 error — something that I suspect everyone would care about.
I might be wrong — and I think you might be doing it in a way that’s safe — but regardless it’s worrisome.
You misunderstand. The “printed approximation” is how floating point numbers are printed; it is understood to be an approximation in the sense the trailing digits that solely come from base 2 to base 10 conversion are omitted, but it is accurate in the sense that it would be parsed back to the same base 2 number. This is what the module Ryu implements currently in base Julia, and handling it correctly is equivalent to reimplementing that. If you are interested in the complexity of the topic, see the papers cited here.
I agree, but it would be great to expose the API of Ryu in the long run. It is one of those niche algorithms where a lot of thought went into speed and correctness and are very useful when you need them.