【问题标题】:How do I force usage of long doubles with Cython?如何在 Cython 中强制使用长双打?
【发布时间】:2014-08-19 09:31:24
【问题描述】:

我提前为我对 C 的了解不足深表歉意:我使用 Python 编写代码,并使用标准 C 函数使用 Cython 编写了一些模块,以显着提高速度。但是,我需要一个高于1e308 的范围(是的,你没看错),这是我目前通过使用double complex 类型和函数cexpcabs 得到的。

我尝试使用函数cexplcabsl,并将我的变量声明为long double complex 类型,但在1e308 之后仍然遇到溢出。这可能意味着我的编译器将长双精度转换为双精度,对吗?但根据维基百科,

使用 GNU C 编译器,long double 是 x86 处理器上的 80 位扩展精度,与用于该类型的物理存储(可以是 96 位或 128 位)无关。[4]

我使用的是 64 位系统和 arch Linux(如果重要的话,还有 Python 2.7.8)。

如何编写强制使用长双精度的 Cython 模块?我需要这么大的数字来进行一些科学计算。

编辑: 使用标志 -m128bit-long-double 编译会得到相同的结果。如here所示,

在 x86-64 编译器中,-m128bit-long-double 是默认选择,因为它的 ABI 指定 long double 将在 16 字节边界上对齐。

所以这似乎没有什么区别。

我还运行了以下程序来检查我系统上的范围:

#include <stdio.h>
#include <float.h>

int main()
{
   printf("Storage size for float : %d \n", sizeof(float));
   printf("Minimum float positive value: %E\n", FLT_MIN );
   printf("Maximum float positive value: %E\n", FLT_MAX );
   printf("Precision value: %d\n", FLT_DIG );

   printf("Storage size for double : %d \n", sizeof(double));
   printf("Minimum double positive value: %E\n", DBL_MIN );
   printf("Maximum double positive value: %E\n", DBL_MAX );
   printf("Precision value: %d\n", DBL_DIG );

   printf("Storage size for long double : %d \n", sizeof(long double));
   printf("Minimum long double positive value: %Le\n", LDBL_MIN );
   printf("Maximum long double positive value: %Le\n", LDBL_MAX );
   printf("Precision value: %d\n", LDBL_DIG );

   return 0;
}

并得到以下输出:

Storage size for float : 4 
Minimum float positive value: 1.175494E-38
Maximum float positive value: 3.402823E+38
Precision value: 6
Storage size for double : 8 
Minimum double positive value: 2.225074E-308
Maximum double positive value: 1.797693E+308
Precision value: 15
Storage size for long double : 16 
Minimum long double positive value: 3.362103e-4932
Maximum long double positive value: 1.189731e+4932
Precision value: 18

所以我猜问题出在我的代码上,对吗?除了声明变量以确保我的程序实际使用长双精度外,我还需要添加任何显式标识符吗?

【问题讨论】:

  • 我没有把它作为答案,因为我不确定它是否正确......但如果你可以添加编译器标志,请尝试 -m96bit-long-double-m128bit-long-double 看看会发生什么. This question might be useful as well.祝你好运。
  • 感谢您的指导!我更新了问题。如何检查我的编译器 (gcc) 是否真的使用 80 位或 96 位长双精度,范围在 1e4392 左右,除了溢出?
  • 我发现 this question 表明我的 C 模块正在返回长双精度,但被 Python 解释为 inf,因为它超过了 double 的大小。就目前而言,我的问题并不是真正正确的问题,因为它建立在一个错误的前提下。我如何投票关闭它?还是应该让这个问题留给其他可能有同样想法的人?
  • 感谢您投入工作并找出问题所在。如果我是你,我会写下我的解决方案,将其作为答案发布,并接受它以供将来参考。这种做法在 SO 上是 actively supported

标签: c gcc cython long-double


【解决方案1】:

正如在问题的编辑中看到的那样,我的系统和编译器通过打印long double 的正确范围来按预期运行,这里的相关变量是LDBL_MAX = 1.189731e+4932

此外,使用 Cython 编写的模块正确地给出了 long double 类型的输出。 但是,由于 Python 本身不支持这种类型(请参阅this 问题),因此返回的值大于我系统上的最大大小 double1.797693E+308,因此等同于 +inf + 0j。所以这根本与 gcc 无关,而是与 Python 以不正确的方式解释长双精度数有关。

我希望可以通过使用另一个可以接受长双输入类型并进一步处理它的 C 模块来解决这个问题,这个子部分的预期结果预计不会超出 double 的范围(或就此而言,即使是float)。

另一种选择可能是使用 Python 库来支持高精度和大范围的数字,可能是GMPY

【讨论】:

    猜你喜欢
    • 2018-07-31
    • 1970-01-01
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 2012-07-07
    相关资源
    最近更新 更多