【问题标题】:Converting remainder of a floating point float/double into an int将浮点浮点数/双精度数的余数转换为整数
【发布时间】:2014-01-30 01:22:44
【问题描述】:

我有一个双(或浮点)数 x:

x = 1234.5678;

现在,问题是,如何将数字分解为 2 个整数,而 int1 将获得该点之前的数字,而 int2 是该点之后的数字。

第一部分很简单,我们可以进行强制转换,或者使用圆形或天花板将第一部分转换为 int,我正在寻找第二部分成为 int2=5678 而不存在任何浮点数。

即来扩展上面的例子:

float x = 1234.5678;
int x1 = (int) x;   // which would return 1234 great.
int x2 = SomeFunction????(x);            // where I need x2 to become = 5678

注意 5678 不应该有任何点。

很高兴收到您的来信。

谢谢 海德

【问题讨论】:

  • @olevegard - 对。但是您必须提前定义此方案所需的小数位数。您不能一次返回 6 位小数,下一次返回 12 位。
  • 计算机在 x 中存储接近 1234.5677490234375 的东西,所以它应该给 5677490234375 吗?更长的时间?
  • (1) 问题指定不正确,因为它说您有 1234.5678 在双精度或浮点数中,但这在双精度或浮点数的常见实现中是不可能的。常见的实现使用基于二进制的浮点,不会精确存储 1234.5678。 (2) 另外,普通的浮点实现没有足够的精度来存储 1234.5678 没有特别的努力;最接近的可表示值更接近 1234.5677。 (3) 问题没有充分说明,因为它没有说明对于 3.25 或 7.53125 等数字应返回多少位。
  • 即使你有一个罕见的使用十进制而不是二进制算术的 C++ 实现,你如何区分 1.04 和 1.4?
  • @HotLicks:表示 1234.5678 到 0.00001 的准确度与表示 1234.5678 不同。问题陈述必须指定给定实际输入的预期结果,而不是希望但不存在的输入。例如,它可以指定所需的结果是将实际输入四舍五入到小数点后四位小数的最接近数字的四位数字。

标签: c++ floating-point int decimal-point


【解决方案1】:

这里有两种方法。

第一个使用std::stringstreamstd::stringstd::strtol,有点老套。它也不是很有效,但它可以完成工作。

第二个需要知道小数位数并使用简单的乘法。注意:此方法不会检查您传入的浮点数是否实际具有该小数位数。

这些方法都不是特别优雅,但它们对于我测试的数字(正面和负面)效果很好。如果您发现错误/错误或有改进建议,请随时发表评论。

编辑:正如 @dan04 所指出的,此方法将为 0.4 返回与 0.04 相同的值。如果你想区分这些,你需要第二个int 来存储小数点后零的数量。

#include <iostream>
#include <sstream>
#include <math.h>

int GetDecimalsUsingString( float number );
int GetDecimals( float number, int num_decimals );

int main() {
    float x = 1234.5678;
    int x1 = (int) x;   // which would return 1234 great.
    float remainder = x - static_cast< float > ( x1 );
    std::cout << "Original : " << x << std::endl;
    std::cout << "Before comma : " << x1 << std::endl;
    std::cout << "Remainder : " << remainder << std::endl;

    // "Ugly" way using std::stringstream and std::string
    int res_string = GetDecimalsUsingString( remainder );

    // Nicer, but requires that you specify number of decimals
    int res_num_decimals = GetDecimals( remainder, 5 );

    std::cout << "Result using string : " << res_string << std::endl;
    std::cout << "Result using known number of decimals : " << res_num_decimals << std::endl;
    return 0;
}

int GetDecimalsUsingString( float number )
{
    // Put number in a stringstream
    std::stringstream ss;
    ss << number;

    // Put content of stringstream into a string
    std::string str = ss.str();

    // Remove the first part of the string ( minus symbol, 0 and decimal point)
    if ( number < 0.0 )
        str = str.substr( 3, str.length() - 1);
    else
        str = str.substr( 2, str.length() - 1);

    // Convert string back to int
    int ret =  std::strtol( str.c_str(), NULL, 10 );

    /// Preserve sign
    if ( number < 0 )
        ret *= -1;

    return ret;
}
int GetDecimals( float number, int num_decimals )
{
    int decimal_multiplier = pow( 10, num_decimals );
    int result = number *  decimal_multiplier;

    return result;
}

输出:

Original : 1234.57
Before comma : 1234
Remainder : 0.567749
Result using string : 567749
Result using known number of decimals : 56774

Ideone

【讨论】:

  • 只需将第二个数字向后存储,因此有效的零在右侧。;)
  • 嗨 Olevegard,谢谢你的回答,非常感谢,我已经使用字符串完成了这项工作,但是,我正在寻找任何类型的内置 C/C++/XCODE“内置- in”函数,看看我是否可以减少这些被认为是资源密集型的函数。我还有另一种解决方案(也有更快的解决方案),而使用指针访问十进制变量的内容并手动解码小数点后的内容(重新发明轮子)。再次感谢 Ole,我正在寻找是否有任何内置函数可以执行此操作。祝你有美好的一天。
【解决方案2】:

我猜没有内置的 C/C++ 命令可以做到这一点,除了以下两种方法:

1) 使用上述转换为字符串,然后扫描回 2 个整数。 2)访问内存变量的内存内容,然后手动解码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-06-12
    • 1970-01-01
    • 2020-02-03
    • 2018-04-26
    • 2018-08-09
    • 2011-11-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多