如何将双精度或浮点数(全部数字)转换为整数?
例如,如果我有一个双精度数0.9332,则函数将返回9332, 1.32001将返回132001。
如何将双精度或浮点数(全部数字)转换为整数?
例如,如果我有一个双精度数0.9332,则函数将返回9332, 1.32001将返回132001。
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;
}
经过更深入的思考,您无法通过简单的强制转换和乘法优雅地处理将 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
9.9999
这样的数字上,其中浮点表示不完全是 99999 / 10000
。当您尝试进行 转换 - 减去实部,将小数部分乘以10,重复 -- 您会重复超过4次。对于像 0.9332
这样的数字,它很简单并且有效,但对于 9.999999
这样的数字,您就没那么幸运了。 - David C. Rankin#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.9332 --> 9332
1.32001 --> 132001
通常情况下,目标在一般情况下并不是严格可能的。
通常情况下,有大约264个不同的double
。 0.9332
和1.32001
不在那组double
中。
让我们来看看最接近的替代方案。
最接近的 double
有以下更为精确的值。一些 double
作为二进制浮点数需要100多个十进制位才能精确表示。
0.933200000000000029487523534...
1.32000999999999990563992469...
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
float
为7位,double
为15位),它们也会衰减成无意义的数字。 - user4581301