【问题标题】:Exact decimal datatype for C++?C ++的精确十进制数据类型?
【发布时间】:2013-03-10 07:30:16
【问题描述】:

PHP 有一个小数类型,它没有浮点数和双精度数的“不准确性”,因此 2.5 + 2.5 = 5 而不是 4.9999999999978325 或类似的东西。

所以我想知道C或C++是否有这样的数据类型实现?

【问题讨论】:

标签: c++ c types decimal precision


【解决方案1】:

Boost.Multiprecision 库有一个名为 cpp_dec_float 的基于十进制的浮点模板类,您可以为其指定任何所需的精度。

#include <iostream>
#include <iomanip>
#include <boost/multiprecision/cpp_dec_float.hpp>

int main()
{
    namespace mp = boost::multiprecision;
    // here I'm using a predefined type that stores 100 digits,
    // but you can create custom types very easily with any level
    // of precision you want.
    typedef mp::cpp_dec_float_100 decimal;

    decimal tiny("0.0000000000000000000000000000000000000000000001");
    decimal huge("100000000000000000000000000000000000000000000000");
    decimal a = tiny;         

    while (a != huge)
    {
        std::cout.precision(100);
        std::cout << std::fixed << a << '\n';
        a *= 10;
    }    
}

【讨论】:

    【解决方案2】:

    是的:

    有 C++ 的任意精度库。
    一个很好的例子是The GNU Multiple Precision arithmetic library

    【讨论】:

    • 请注意,这实际上并不能“解决”一般问题:它会将其推迟到您可以选择的更深的精度级别。总比没有好,但 - 不幸的是 - 仅一步之遥,朝着不可能的“无限精度”迈进。无论如何,不​​错的提示!
    • 说“不:”然后用不同的措辞描述完全相同的概念有什么意义? “不”代表什么?
    • @EmilioGaravaglia:不。不一样。您是在暗示精度存在限制。那没有。这就像在向更大的整数迈出一步。我们可以有你喜欢的整数(只要你有记忆)。
    • “随心所欲”
    • @EmilioGaravaglia:重读后。您似乎混淆了精确无限(exact)和任意(exact)。该库的重点是您永远不会失去输入的精度。使用的内部表示应该保持至少与输入一样精确的表示。任何会导致像1/3 这样的表示丢失的操作都会被推迟,以便以后可以取消。有理数(如 pie)不会转换为十进制表示(就像你手工计算时一样)。
    【解决方案3】:

    如果您正在寻找支持货币/货币的数据类型,请尝试以下操作: https://github.com/vpiotr/decimal_for_cpp

    (这是仅标题的解决方案)

    【讨论】:

      【解决方案4】:

      总会有一些精确度。在任何数字表示的任何计算机上,总会有可以准确表示的数字,而其他数字则不能。

      • 计算机使用 base 2 系统。 0.5 (2^-1)、0.125 (2^-3)、0.325 (2^-2 + 2^-3) 等数字将被准确表示(上述情况为 0.1、0.001、0.011)。

      • 在以 3 为底的系统中,这些数字无法准确表示(一半为 0.111111...),但其他数字可以准确表示(例如 2/3 为 0.2)

      • 即使在人基 10 系统中,也存在无法准确表示的数字,例如 1/3。

      • 您可以使用有理数表示,以上所有内容都是准确的(1/2、1/3、3/8 等),但总会有一些无理数。您实际上还受到此表示的整数大小的限制。

      • 对于每个不可表示的数字,您可以扩展表示以明确包含它。 (例如比较有理数和表示a/b + c/d*sqrt(2)),但总会有更多的数字仍然无法准确表示。有一个数学证明是这样说的。

      所以 - 让我问你这个问题:你到底需要什么?也许对基于十进制的数字进行精确计算,例如在一些货币计算中?

      【讨论】:

        【解决方案5】:

        你问的是反物理。

        phyton(以及 C++)所做的就是通过将结果四舍五入以将其打印出来,通过减少有效数字的数量来消除不准确性:

        double x = 2.5;
        x += 2.5;
        std::cout << x << std::endl;
        

        只是让 x 以 6 位小数精度打印(而 x 本身超过 12 位),并将四舍五入为 5,消除不精确。

        替代方案根本不使用浮点,并实现仅执行整数“缩放”算术的数据类型:25/10 + 25/10 = 50/10;

        但是请注意,这将减少每个整数类型表示的上限。精度(和准确度)的提高将导致更快地到达溢出。

        有理算术也是可能的(每个数字由一个“分子”和一个“分母”表示),除法没有精度损失,(事实上,除非精确,否则不会这样做)但同样,随着值的增加随着运算次数的增加(数字越不“有理”,分子和分母就越大)溢出的风险就越大。

        换句话说,使用有限数量的比特这一事实(无论如何组织)总是会导致您必须在小数字方面付出代价。

        【讨论】:

          【解决方案6】:

          我想你说的是 PHP 中的二进制计算器。不,C 运行时或 STL 中没有。但如果你愿意,你可以自己写。

          这是使用 Facebook 的 HipHop for PHP 编译的 C++ 版本的 BCMath: http://fossies.org/dox/facebook-hiphop-php-cf9b612/dir_2abbe3fda61b755422f6c6bae0a5444a.html

          【讨论】:

            【解决方案7】:

            作为一种高级语言PHP 只是切断了你所谓的“不准确”,但它肯定存在。在 C/C++ 中,您可以通过将结果转换为整数类型来达到类似的效果。

            【讨论】:

            • 如果精度如此重要,那么强制转换为整数将是一件非常愚蠢的事情。在结果为 4.999999999978325 的情况下它可能工作正常,但对于不应四舍五入为整数的任何内容,这将是一个非常糟糕的调用。
            • @ddriver 那么,您认为 PHP 是如何决定将 2.5+2.5 的结果表示为 5 的?如果它不应该被四舍五入,就不要四舍五入,抱歉重言式。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-11-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-12-12
            • 1970-01-01
            相关资源
            最近更新 更多