You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There already is implementation that allows to calculate $integer \times10 \textasciicircum decimalExponent$ with correct rounding.
It may be useful to users.
The API can look like this:
FASTFLOAT_CONSTEXPR20
typename std::enable_if<is_supported_float_type<double>::value, double>::type
multiply_integer_and_power_of_10(uint64_t mantissa,
int decimal_exponent) noexcept;
I haven't come up with a good name, so the name is (intentionally?) ugly and it should be improved.
If you are interested in it, I have the draft code ready.
Motivation
We alread have it so why not?
Other than that, the obvious motivation is that it is not trivial to multiply an integer by a power of 10 to get a specific result.
Warning
Disclaimer: everything I write is to the best of my knowledge, I may be wrong.
This warning is here so I don't litter the rest of the text with "my understanding is that..." and the like.
Notice that multiplying by pow(10., 23) overshoots the exact value, and multiplying by hardcoded power of 10 1e23 undershoots.
Either of the behavior may or may not be desirable, but it's nice to have an option with correct rounding.
Parsing strings (with HUGE caveat)
You can imagine a UI control where the user can input mantissa and decimal exponent separately, in this case, instead of "printing" the whole number into a buffer and then calling from_chars(), the programmer can interpret the mantissa and the exponent parts separately and just call multiply_integer_and_power_of_10().
Another example is the need to parse strings where the string is inconvenient or impossible to acquire in full, e.g. when it is received via network. So again the programmer can record significant decimal digits, track the decimal point and interpret decimal exponent without needing a buffer (of unknown size), and compose the floating point number using multiply_integer_and_power_of_10(), e.g.:
0.000...(like, 100 zeros)...1234567890123456789e000...(opps, more zeros)...23
Since this number has (no more than) 19 significant decimal digits multiply_integer_and_power_of_10() will give the correct result.
With this exaggerated example I'm trying to illustrate that in such cases it is non-trivial to replicate the behavior of from_chars() and get the correct result that it would give.
Maybe there should be an interface receiving input iterators or something, but that's the whole separate issue.
The HUGE caveat is that uint64_t can only fully accommodate at most 19 decimal digits, i.e. values <=9`999`999`999`999`999`999.
UI control can be restricted to 19 significant decimal digits and multiply_integer_and_power_of_10() will work perfectly in that case.
In other cases, if the number that eventually arrives is more than 19 significant decimal digits we run into all sorts of problems, of which the most difficult to solve is "tie to even".
"Tie to even" problem example. (Click/tap to expand.)
To illustrate the problem we can write a program like this:
Notice that halfway0, which is excatly half way between even0 and odd (different by the least significant bit: 1.0000000000001p+48), is rounded down to even0,
while halfway1 between odd and even1 is rounded up to the next number even1.
Nobody knows how to solve this problem in general other than by brute force multiplication using extended precision (which is significantly non-trivial).
Multiplying floating point values by powers of 10
Among many examples, converting units with different SI prefixes seems to be the most obvious one.
It is not very hard to come up with this example:
This result may or may not be desirable, but merely switching the SI prefix and getting result other than 1234.5678901 is probably surprising to the user.
Having a hypothetical function inverse to multiply_integer_and_power_of_10(), e.g.
int64_tdecompose_to_integer_and_power_of_10(double number, int decimalExponent) {
// https://github.com/jk-jeon/dragonbox by Junekey Jeonconstauto [mantissa, exponent, isNegative] = jkj::dragonbox::to_decimal(number);
decimalExponent = exponent;
constauto m = static_cast<int64_t>(mantissa);
return isNegative ? -m : m;
}
we can generally perfectly multiply by powers of 10 with unsurprising result:
int e;
constauto m = decompose_to_integer_and_power_of_10(seconds.count(), e);
std::cout << "seconds.count() = " << m << " * 10^" << e << '\n';
PRINTLN(multiply_integer_and_power_of_10(m, e + 18));
tl;dr:
There already is implementation that allows to calculate$integer \times10 \textasciicircum decimalExponent$ with correct rounding.
It may be useful to users.
The API can look like this:
I haven't come up with a good name, so the name is (intentionally?) ugly and it should be improved.
If you are interested in it, I have the draft code ready.
Motivation
We alread have it so why not?
Other than that, the obvious motivation is that it is not trivial to multiply an integer by a power of 10 to get a specific result.
Warning
Disclaimer: everything I write is to the best of my knowledge, I may be wrong.
This warning is here so I don't litter the rest of the text with "my understanding is that..." and the like.
E.g. it is easy to come up with this example:
uninteresting stuff
which outputs
Notice that multiplying by
pow(10., 23)overshoots the exact value, and multiplying by hardcoded power of 101e23undershoots.Either of the behavior may or may not be desirable, but it's nice to have an option with correct rounding.
Parsing strings (with HUGE caveat)
You can imagine a UI control where the user can input mantissa and decimal exponent separately, in this case, instead of "printing" the whole number into a buffer and then calling
from_chars(), the programmer can interpret the mantissa and the exponent parts separately and just callmultiply_integer_and_power_of_10().Another example is the need to parse strings where the string is inconvenient or impossible to acquire in full, e.g. when it is received via network. So again the programmer can record significant decimal digits, track the decimal point and interpret decimal exponent without needing a buffer (of unknown size), and compose the floating point number using
multiply_integer_and_power_of_10(), e.g.:Since this number has (no more than) 19 significant decimal digits
multiply_integer_and_power_of_10()will give the correct result.With this exaggerated example I'm trying to illustrate that in such cases it is non-trivial to replicate the behavior of
from_chars()and get the correct result that it would give.Maybe there should be an interface receiving input iterators or something, but that's the whole separate issue.
The HUGE caveat is that
uint64_tcan only fully accommodate at most 19 decimal digits, i.e. values <=9`999`999`999`999`999`999.UI control can be restricted to 19 significant decimal digits and
multiply_integer_and_power_of_10()will work perfectly in that case.In other cases, if the number that eventually arrives is more than 19 significant decimal digits we run into all sorts of problems, of which the most difficult to solve is "tie to even".
"Tie to even" problem example. (Click/tap to expand.)
To illustrate the problem we can write a program like this:
which outputs
Notice that
halfway0, which is excatly half way betweeneven0andodd(different by the least significant bit: 1.0000000000001p+48), is rounded down toeven0,while
halfway1betweenoddandeven1is rounded up to the next numbereven1.Nobody knows how to solve this problem in general other than by brute force multiplication using extended precision (which is significantly non-trivial).
Multiplying floating point values by powers of 10
Among many examples, converting units with different SI prefixes seems to be the most obvious one.
It is not very hard to come up with this example:
which outputs
This result may or may not be desirable, but merely switching the SI prefix and getting result other than
1234.5678901is probably surprising to the user.Having a hypothetical function inverse to
multiply_integer_and_power_of_10(), e.g.we can generally perfectly multiply by powers of 10 with unsurprising result:
outputs
Again this may or may not be desirable, but it's nice to have this option.
One more example in the other direction:
outputs