如何正确地将float与int相乘并获得仅受有效数字影响的结果?

Joh*_*itb 6 c++ floating-point multiplication

我有代码在float(表示第二个)和int64(表示纳秒)之间进行转换,从float中6小数位

int64_t nanos = f * 1000000000LL;
Run Code Online (Sandbox Code Playgroud)

但是,存储在浮点数中的许多十进制值无法在二进制浮点数中精确表示,因此我得到的结果就像14199999488我的浮点数一样14.2f.目前我通过计算小数点后的大量数字来解决这个问题

const float logOfSecs = std::log10(f);

int precommaPlaces = 0;
if(logOfSecs > 0) {
   precommaPlaces = std::ceil(logOfSecs);
}

int postcommaPlaces = 7 - precommaPlaces;
if(postcommaPlaces < 0) {
   postcommaPlaces = 0;
}
Run Code Online (Sandbox Code Playgroud)

然后将浮动打印成一个字符串让Qt正确地绕浮标.然后我将字符串解析为前后逗号整数,并使用整数运算将它们多个.

const QString valueStr = QString::number(f, 'f', postcommaPlaces);
qint64 nanos = 0;
nanos += valueStr.section(".", 0, 0).toLongLong() * 1000000000LL;
if(postcommaPlaces) {
   nanos += valueStr.section(".", 1).toLongLong() * 
     std::pow(10.0, 9 - postcommaPlaces);
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我想知道是否有更好的,或许更快的方法来做到这一点?

Ola*_*che 2

例如,如果您想四舍五入到小数点后一位

#include <iostream>

int main()
{
    float f = 14.2f;
    long long n = f * 1000000000LL;
    std::cout << "float: " << n << '\n';
    n = (f + 0.05) * 10;
    n *= 100000000LL;
    std::cout << "rounded: " << n << '\n';
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

小数点后两位为(f + 0.005) * 100, ..., 小数点后六位

n = ((long long)((f + 0.0000005) * 1000000)) * 1000LL;
Run Code Online (Sandbox Code Playgroud)

如果要考虑有效数字(所有数字),则必须先取小数位log10(f),然后调整四舍五入。

但正如 @MarkB 已经说过的,如果你int64_t首先使用,你根本不需要这个。