将数的小数部分转换为整数的C++方法

6

我需要将一个数字的小数部分转换为整数,不要包含逗号,例如我有3.35,我只想得到35部分,不要有零或逗号。

因为我使用了modf()函数来提取小数部分,但是它给出了0.35。如果有任何方法可以做到这一点或过滤掉“0.”部分,如果您能用尽可能少的代码向我展示如何做到这一点,我将非常感激。


8
是否总是只有两位小数?将其乘以100并转换为整数如何? - Vaughn Cato
2
将其格式化为字符串,然后要么复制小数点后的所有内容,要么删除第一个数字字符之前的所有内容。(如果需要,可以将其转换回整数) - Mordachai
3.35 的二进制表示很可能是 3.349999986f 或者类似的值。3.350 的二进制表示相同。给定输入 3.35 和 3.350,您期望得到什么样的输出呢? - MSalters
1
请注意,doublefloat类型无法精确表示3.35,因为这是二进制中的无限周期小数。如果您想要精确表示,请使用像建议的decimal64或甚至是乘以100的int类型。 - Gunther Piez
@MSalters 精确到小数点后16位为3.3500000000000001。 - Gunther Piez
可能会有损失但非常简单:double n=3.35; double frac=n-int64_t(n);//0.35 - hanshenrik
8个回答

4

比将其转换为字符串然后再转回来更加高效:

int fractional_part_as_int(double number, int number_of_decimal_places) {
    double dummy;
    double frac = modf(number,&dummy);
    return round(frac*pow(10,number_of_decimal_places));
}

3
#include <iostream>
#include <cmath>

double round(double r) {
    return (r > 0.0) ? std::floor(r + 0.5) : std::ceil(r - 0.5);
}

double floor_to_zero(double f) {
    return (f > 0.0) ? std::floor(f) : std::ceil(f);
}

double sign(double s) {
    return (s < 0.0) ? -1.0 : 1.0;
}

int frac(double f, int prec) {
    return round((f - floor_to_zero(f)) * prec) * sign(f);
}

int main() {
    double a = 1.2345;
    double b = -34.567;
    std::cout << frac(a, 100) << " " << frac(b, 100) << std::endl; // 23 57
}

0

另一种解决方案

int precision= 100;
double number = 3.35;
int f = floor(xx);
double temp = ( f - number ) * -1;
int fractional_part = temp * precision;

1
number - f 怎么样,而不是 (f - number) * -1 - Pete Becker
2
这对于负数不起作用。-0.1得到90。 - digitalvision

0
如果你需要将它作为字符串,一个相当简单的C风格解决方案是(应该适用于变量数量的小数位):
    double yourNumber = 0.35f;
    char buffer[32];
    snprintf(buffer, 32, "%g", yourNumber);
    strtok(buffer, "."); // Here we would get the part before . , should still check
    char* fraction = strtok(NULL, ".");
    int fractionAsInt = atoi(fraction);

这个例子在处理错误字符串时缺乏错误处理,如果你只需要固定数量的小数位数,那么算术方法会更好。


0

应该可以这样做:

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

static int get_frac(double value, unsigned short precision)
{
    return (int)((value - (long)value) * pow(10, precision));
}

static int get_frac_no_trailing_zeros(double value, unsigned short precision)
{
    int v = get_frac(value, precision);
    while (v % 10 == 0)
        v /= 10;
    return v;
}

int main(int argc, char *argv[])
{
    double v;

    v = 123.4564;
    printf("%.4f = %d\n", v, get_frac(v, 2));
    printf("%.4f = %d\n", v, get_frac(v, 4));
    printf("%.4f = %d\n", v, get_frac(v, 6));
    printf("%.4f = %d\n", v, get_frac_no_trailing_zeros(v, 6));

    return EXIT_SUCCESS;
}

您可能还想要避免调用pow函数,可以让用户在第一次输入时提供一个10的幂次方数,或者使用查找表。


0

使用一些STL魔法,这里是示例代码:

typedef std::pair<int, int> SplitFloat;

SplitFloat Split(float value, int precision)
{
    // Get integer part.
    float left = std::floor(value);
    // Get decimal part.
    float right = (value - left) * float(std::pow(10, precision));

    return SplitFloat(left, right);
}

这可以被改进,但非常简单明了。


0

我刚刚做了与你尝试做的事情类似的事情,虽然我还是非常新手。然而,或许这会对未来有所帮助,因为我在寻找解决我的问题的结果时来到了这里。

第一步是确保包含3.35的变量是一个双精度浮点数,但这可能是显而易见的。

接下来,创建一个只包含整数的变量,并将其值设置为双精度浮点数的值。然后它将仅包含整数部分。

然后从双精度浮点数中减去整数部分(int)。你将剩下分数/小数值。从那里开始,只需乘以100。

超过百分之一的小数值,你需要进行更多的配置,但使用if语句应该很容易。如果小数值大于0.99,则乘以1000等。


-1

这是我会怎么做。

#include <sstream>
#include <string>

int main()
{
    double d = yourDesiredNumber; //this is your number
    std::ostringstream out;
    out << setprecision(yourDesiredPrecision) << std::fixed 
        << std::showpoint << d;
    std::istringstream in(out.str());
    std::string wholePart; //you won't need this. 
    int fractionalPart;  
    std::getline(in, wholePart, '.');
    in >> fractionalPart;
    //now fractionalPart contains your desired value.
}

我相信,你可以用一个 stringstream 对象代替两个不同的 istringstreamostringstream 对象,但是我不确定细节(从未使用过该类),所以在示例中没有使用它。

1
@RichardJ.RossIII:老实说,我在等你的回答,看看你会怎么做。 - Armen Tsirunyan

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