Как заставить использование длинных пар с Cython?
Заранее извиняюсь за плохое знание C: я использую Python для написания кода и написал несколько модулей на Cython, используя стандартные функции C, чтобы добиться значительного увеличения скорости. Однако мне нужен диапазон выше, чем 1e308
(да, вы правильно прочитали), что я сейчас получаю, используя тип double complex
и функции cexp
а также cabs
,
Я пытался использовать функции cexpl
а также cabsl
и объявил мои переменные типа long double complex
, но я все еще сталкиваюсь с переполнением после 1e308
, Это, вероятно, означает, что мой компилятор конвертирует длинные двойные числа в двойные, верно? Но согласно Википедии,
В компиляторе GNU C long double - это 80-битная расширенная точность на процессорах x86, независимо от физической памяти, используемой для типа (которая может быть 96 или 128 битами).[4]
Я использую 64-битную систему с Arch Linux (и Python 2.7.8, если это имеет значение).
Как мне написать модуль Cython, который заставляет использовать длинные двойники? Мне нужны такие большие цифры для некоторых научных расчетов, которые я делаю.
Изменить: Компиляция с флагом -m128bit-long-double дает тот же результат. Как указано здесь,
В компиляторе 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
Так что я думаю, проблема в моем коде, верно? Есть ли какие-то явные идентификаторы, которые мне нужно добавить, кроме объявления переменных, чтобы моя программа действительно использовала длинные двойные числа?
1 ответ
Как видно из редактирования вопроса, моя система и компилятор работали так, как ожидалось, печатая правильный диапазон для long double
соответствующая переменная здесь LDBL_MAX = 1.189731e+4932
Кроме того, модуль, написанный на Cython, правильно выдавал вывод типа long double
, Однако, поскольку этот тип изначально не поддерживается в Python (см. Этот вопрос), возвращаемое значение было больше максимального размера double
,1.797693E+308
в моей системе и, следовательно, приравнивается к +inf + 0j
, Так что это вообще не было связано с gcc, а с Python, неправильно интерпретирующим длинные двойные числа.
Надеюсь, я смогу обойти это, работая с другим модулем C, который может принимать длинные двойные типы ввода и обрабатывать его дальше; ожидаемые результаты из этой части не должны выходить за пределы диапазона double
(или в этом отношении, даже float
).
Другой вариант может заключаться в использовании библиотек с Python, которые могут поддерживать числа высокой точности и диапазона, возможно, GMPY.