【问题标题】:Pow precision with unsigned longs无符号长整数的 Pow 精度
【发布时间】:2015-10-22 12:48:08
【问题描述】:

所以我正在尝试做 pow (x, y)。其中 x 和 y 是无符号长整数,结果存储在无符号长整数中。这个结果将小于 2^63,所以我应该能够做到。 但由于它返回一个浮点数,所以我得到的大数结果不准确。无论如何,如果不使用 bignum 之类的外部库,是否可以获得准确的结果? 我知道我可以简单地执行 x*x a Y 次,但这是我试图避免的,因为我试图让我的程序更快。

【问题讨论】:

  • 你的代码在哪里?您可能需要将浮点数四舍五入到最接近的整数。
  • pow 执行exp(y*log(x)),速度很快,但存在精度问题。
  • I 问题是不是1个数不准确,而是37个。 answer = pow(a, b);
  • 我没有标记为重复,因为你一开始不知道该怎么做,但你可能会看看这个:stackoverflow.com/questions/101439/…

标签: c precision pow


【解决方案1】:

pow 函数返回一个具有精度问题的 double,当您将其转换为 long 时,您最肯定会遇到精度问题。据我所知,如果您不使用库,那么仅使用 pow 函数就不可能获得准确的结果。

你也可以看看Exponentiation by squaring,也可以看看barak manosanswer,在那里你可以尝试实现你自己的pow函数

unsigned long long pow(unsigned long long x,unsigned int y)
{
    unsigned long long res = 1;
    while (y > 0)
    {
        if (y & 1)
            res *= x;
        y >>= 1;
        x *= x;
    }
    return res;
}

【讨论】:

  • 这种方法对非常大的数字有效吗?比如 10000^10000(x^y)?因为我想始终将值保持在 2^63-1 以下。所以我试图尽可能接近 2^63-1,然后我会在这部分进行计算,取结果,并将其带到下一个计算,直到我的 y 变得足够小以进行计算立即。
  • @LifeisHard: 10000^10000 不小于2^63,所以你会有其他问题。除了您需要(大约)125 个其他宇宙来存储所有这些数字之外。
  • @Jongware:10000^10000 大于 2^63,但仍可轻松放入网页,尽管不在评论中:1 后跟 40000 0s。
  • @chqrlie: ... 10000^10 根据谷歌的计算器,1e+40。那是 10³¹ Gb——对于一个网页来说有点大——而且正在讨论的数字是一个完整的 Googol 更大。
  • 创建函数unsigned long long pow(unsigned long long x,unsigned int y) ... 是导致一些讨厌的错误的好方法。 C 没有同名函数的签名。掩盖/隐藏符合标准的 `double pow( double, double );功能。
【解决方案2】:

pow 根据定义是不准确的。它使用exp(y*log(x)) 作为模拟x ^ y 的一种方式。如果您想要完全精确,您需要使用外部库或制作您自己的 pow 版本。

【讨论】:

    【解决方案3】:

    我不确定您的代码。但我猜你的代码是这样的

    unsigned long x,y;
    x=...//
    y=...//
    
    unsigned long res=pow(x,y);
    

    这是不对的。因为 pow() 总是返回 double 类型。

    double pow(double x, double y) 
    

    这就是你得到双类型数字的原因。

    要获得正确的数字,您可以这样做:

        unsigned long x,y;
        x=...//
        y=...//
    
        unsigned long res=(unsigned long)pow(x,y);
    

    【讨论】:

    • 这并不能解决 OP 的问题:“因为它返回一个浮点数,所以我得到的大数结果不准确”。
    • @Jongware 你确定 res 的值是浮点数吗?
    • 您的解释令人困惑:只要通过#include <math.h> 正确声明pow 第一个选项没有问题,到unsigned long 的转换是隐式的,编译器将生成正确的代码.相反,如果 pow 没有声明,添加显式转换不会改变任何内容:编译器将假定函数具有 int pow(int,int); 原型,生成的代码将完全错误。
    猜你喜欢
    • 2012-04-19
    • 1970-01-01
    • 2017-10-17
    • 1970-01-01
    • 2014-02-04
    • 2015-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多