如何将双精度浮点数或单精度浮点数(所有数字)转换为整数?

3

如何将双精度或浮点数(全部数字)转换为整数?

例如,如果我有一个双精度数0.9332,则函数将返回9332, 1.32001将返回132001。


3
你做不到。大多数浮点数都是以十进制格式的无限数字系列表示的。这几乎每天都会以各种形式出现。只需搜索浮点即可。 - doug
2
很难做,因为很难确定浮点数的“结束”位置。它们不是精确的,例如10可能是9.99999999999999。在一定数量的位数后(float为7位,double为15位),它们也会衰减成无意义的数字。 - user4581301
3
那么你可以将其乘以10的5次方,并分配给一个整数类型。 - P.W
好的,这给了我一些可以处理的东西。我将尝试计算数字、评估第六个数字以及字符串理论。谢谢! - user8616658
2
@doug:每个二进制浮点数都可以用有限数量的十进制数字精确表示。 - Eric Postpischil
显示剩余8条评论
5个回答

1
this will work ! question is similar to this one :
https://dev59.com/N1XTa4cB1Zd3GeqPzj7r

#include <iostream>
#include <math.h>
using namespace std;
int getFractionDigitsCount(float );
int main()
{
    float a=1.9332;
    int p = getFractionDigitsCount(a);
    cout<<"answer is : "<< a * pow(10,p);

    return 0;
}
 int getFractionDigitsCount(float d) {
    if (d >= 1) { //we only need the fraction digits
        d = d - (long) d;
    }
    if (d == 0) { //nothing to count
        return 0;
    }
    d *= 10; //shifts 1 digit to left
    int count = 1;
    while (d - (long) d != 0) { //keeps shifting until there are no more fractions
        d *= 10;
        count++;
    }
    return count;
}

我已经编译了它,程序运行良好,并且问题没有提到处理负值。 - Parse Shyam

0

你不必要地把自己逼入了一个死角。如果你需要正确的十进制浮点数结果,你应该使用像dec64这样的十进制浮点数来进行计算,而不是试图将错误的结果强行转换为正常状态。


0

经过更深入的思考,您无法通过简单的强制转换和乘法优雅地处理将 double(或 float)直接转换为整数,因为浮点数的限制不能准确地表示所有值,导致小数点重复出现等问题,这使得分数部分方法在像 9.999999 这样的数字上失败。

但是,您可以使用一个中介的 string 并从字符串中解析数字来避免所有陷阱。(如果浮点数已经在程序中,则通过将数字转换为 stringstream,或者最初将浮点值读取为 string 来实现。)

然后,只需处理负值或以前导零开头的值(例如 -31.3333)的情况,然后将原始浮点值的数字复制(.push_back())到一个中间字符串中,然后调用您的转换为 .stoi()、.stol() 或 .stoll()。您可以使用 try {...} catch {...} 异常处理来处理任何失败的转换。

对于返回 long long 值的函数,你可以这样做:

#define LONGDIGITS 19

long long sdigits (std::string s)
{
    int start = 0;                          /* flag skip leading 0 */
    size_t n = 0, maxdigits = LONGDIGITS;   /* set max digits */
    long long l = 0;                        /* int to hold conversion */
    std::string result;                     /* string to hold digits */

    if (s[0] == '-') {              /* if leading '-' */
        result.push_back ('-');     /* save for sign */
        maxdigits++;                /* increment max by 1 */
    }
    for (auto c : s) {              /* loop over all chars */
        if (isdigit (c)) {          /* if not digit skip */
            if (c != '0')           /* if not 0, the set start flag */
                start = 1;
            if (start) {                /* if start set */
                result.push_back (c);   /* add digit to result */
                n++;                    /* increment digit count */
            }
        }
        if (n == maxdigits)         /* if digit count == max */
            break;                  /* break */
    }
    try {                           /* try conversion to long long */
        l = std::stoll (result);
    }
    catch ( std::exception& e ) {   /* catch/handle exception */
        std::cerr << "error: std::" << e.what() << " out_of_range.\n";
    }

    return l;   /* return long long value, or 0 on error */
}

把它放在一个简短的例子中,你可以这样做:

#include <iostream>
#include <string>
#include <limits>
#include <cctype>

#define LONGDIGITS 19

long long sdigits (std::string s)
{
    int start = 0;                          /* flag skip leading 0 */
    size_t n = 0, maxdigits = LONGDIGITS;   /* set max digits */
    long long l = 0;                        /* int to hold conversion */
    std::string result;                     /* string to hold digits */

    if (s[0] == '-') {              /* if leading '-' */
        result.push_back ('-');     /* save for sign */
        maxdigits++;                /* increment max by 1 */
    }
    for (auto c : s) {              /* loop over all chars */
        if (isdigit (c)) {          /* if not digit skip */
            if (c != '0')           /* if not 0, the set start flag */
                start = 1;
            if (start) {                /* if start set */
                result.push_back (c);   /* add digit to result */
                n++;                    /* increment digit count */
            }
        }
        if (n == maxdigits)         /* if digit count == max */
            break;                  /* break */
    }
    try {                           /* try conversion to long long */
        l = std::stoll (result);
    }
    catch ( std::exception& e ) {   /* catch/handle exception */
        std::cerr << "error: std::" << e.what() << " out_of_range.\n";
    }

    return l;   /* return long long value, or 0 on error */
}

int main (void) {

    std::string s;
    long long l;

    std::cout << "enter double in range of 64-bit int: ";
    if (!(std::cin >> s)) {
        std::cerr << "err: invalid input.\n";
        return 1;
    }

    l = sdigits (s);

    std::cout << s << " -> " << l << '\n';
}

可能有很多方法可以做到这一点,所以不要把这个看作是唯一的方法,但你可以准确地处理转换并进行验证,以便识别任何失败。

示例用法/输出

$ ./bin/double_all_digits
enter double in range of 64-bit int: 0.9332
0.9332 -> 9332

$ ./bin/double_all_digits
enter double in range of 64-bit int: 1.32001
1.32001 -> 132001

负值也同样被正确处理:
$ ./bin/double_all_digits
enter double in range of 64-bit int: -0.9332
-0.9332 -> -9332

通过使用字符串进行中间解析,您可以避免浮点重复小数问题:
$ ./bin/double_all_digits
enter double in range of 64-bit int: 9.999999
9.999999 -> 9999999

$ ./bin/double_all_digits
enter double in range of 64-bit int: -31.3333
-31.3333 -> -313333

通过使用 try {...} catch {...} 异常处理,您可以捕获任何 out_of_range 转换。最大允许的转换为 long long 是:
$ ./bin/double_all_digits
enter double in range of 64-bit int: 0.9223372036854775807
0.9223372036854775807 -> 9223372036854775807

当加1时,long long的值超出范围:

$./bin/double_all_digits
enter double in range of 64-bit int: 0.9223372036854775808
error: std::stoll out_of_range.
0.9223372036854775808 -> 0

你的第一段是错误的。你可以从二进制浮点数中提取所有十进制数字。只是可能有太多(不切实际)的数字来表示精确值。 - Alexey Frunze
当然,你可以提取它们,这意味着你不能直接转换它们而不遇到小数部分的问题。这是你的意思吗? - David C. Rankin
1
注意整数部分,将其移除/减去。直到余数为0,乘以10,注意整数部分,将其移除/减去...你在这里看到了什么问题吗?没有任何问题。没有四舍五入或截断。 - Alexey Frunze
问题出现在像 9.9999 这样的数字上,其中浮点表示不完全是 99999 / 10000。当您尝试进行 转换 - 减去实部,将小数部分乘以10,重复 -- 您会重复超过4次。对于像 0.9332 这样的数字,它很简单并且有效,但对于 9.999999 这样的数字,您就没那么幸运了。 - David C. Rankin
你并没有真正拥有9.9999。确切的数字略有不同。你拥有的是能够恢复所有数字(超过五个)的确切数字。 - Alexey Frunze
显示剩余3条评论

0
你可以使用C++标准库中的字符串函数将浮点数转换为整数。
#include <iostream>
#include <string>
#include <cctype>

int floatDigitToInt(float num) {
    std::string str_f = std::to_string(num);
    // here one can check NaN, inf etc..
    std::string str_i;
    for (int i = 0; i < str_f.length(); ++i) {
        if (std::isdigit(str_f[i])) {
            str_i += str_f[i];
        }
    }
    return std::stoi(str_i);
}

int main() {
    float num_f = 1.32001;
    std::cout << floatDigitToInt(num_f);
    return 0;
}

0
如何将double或float(所有数字)转换为int?
0.9332  --> 9332  
1.32001 --> 132001

通常情况下,目标在一般情况下并不是严格可能的。
通常情况下,有大约264个不同的double0.93321.32001不在那组double中。


让我们来看看最接近的替代方案。

最接近的 double 有以下更为精确的值。一些 double 作为二进制浮点数需要100多个十进制位才能精确表示。

0.933200000000000029487523534...
1.32000999999999990563992469...

为了将这些值“转换为整数”进行合理的打印,我们需要选择所需的精度。
假设我们选择小数点后固定的数字个数。(对于小的double值来说并不是一个好主意,因为它们全部变成“0”),代码可以根据需要对字符串进行后处理。
int len = snprintf(NULL, n, "%.*f", 16, double_value);
char buf(len + 1];
snprintf(buf, sizeof buf, "%.*f", 16, double_value);
char *dp = strchr(buf, '.');  // Look for the decimal point - might be `,` in some locales
if (dp) {
  size_t len = strlen(dp + 1);
  memmove(dp, dp + 1, len + 1); // shove over fraction
  while (len > 0 && dp[len - 1] == '0') {
    dp[--len] = '\0';  // lop off trailing zeros.
  }
} 

现在buf[]仅包含数字(除非是无穷大/NaN),适合于strto...()转换为某种整数类型 - 如果它“适合”的话。 buf[]可能包含数百个数字,因为DBL_MAX通常约为3.0e308左右。 OP的目标并未表达为非常大/小的double


对于一定范围内的 double,可以使用 "%.*g",它会“从结果的小数部分中移除尾随零”,然后处理该字符串以删除 '.'

printf("%.16g\n", 0.9332);
printf("%.16g\n", 1.32001);

输出

0.9332
1.32001

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接