2015-11-26 11 views
1

Я работаю над численным анализом с использованием решателя (программирование основано на объектно-ориентированном C++), скомпилированном с двойной точностью, а мой блок - 64-разрядный. Моя проблема заключается в том, что когда решатель вычисляет большое число - например, -1.45 для мощности 21, чтобы взять фактический пример - и суммирует его в выделенной памяти, передавая это значение существующей переменной, он преобразуется в 0. Таким образом, Конечно, когда я позже использую эту переменную в делении, я получаю ошибку сегментации. Я не понимаю, как работает этот процесс, и потому, что я использую DP, я не вижу, как исправить эту проблему. Может ли кто-нибудь дать мне руку с этим вопросом, пожалуйста?Обработка переменных большого числа цифр в объектно-ориентированном C++

В случае, если это помогает: я просто проверил тест, в котором я указываю a = -1.45e + 21, и «распечатайте» значение, которое корректно возвращается решателем. Но когда я не использую показатель «e» и введите полное значение (с 19 нулями), я получаю 0 взамен. Поэтому я думаю, что проблема/ограничение исходит из числа цифр, любых идей? Благодаря !

Редактировать: Я публикую краткую информацию о шагах, которые я выполняю, для вычисления одной из переменных, представляющих проблему. Другие аналогично определены. Сначала я инициализирует списки указателей поля:

PtrList<volScalarField> fInvFluids(fluidRegions.size()); 

Где класс volScalarField просто массив в два раза. Затем я заполнить списки указателей поля:

fInvFluids.set 
    (
     i, 
     new volScalarField 
     (
      IOobject 
      (
       "fInv", 
       runTime.timeName(), 
       fluidRegions[i], 
       IOobject::NO_READ, 
       IOobject::AUTO_WRITE 
      ), 
      fluidRegions[i], 
      dimensionedScalar 
      (
       "fInv", 
       dimensionSet(3,1,-9,-1,0,0,0), 
       scalar(0) 
      ) 
     ) 
    ); 

После этого я установил полевые области:

volScalarField& fInv = fInvFluids[i]; 

И, наконец, я вычислить значение:

// Info<< " ** Calculating fInv   **\n"; 
    fInv = gT*pow(pow(T/Tlambda, 5.7)*(1 - pow(T/Tlambda, 5.7)), 3); 

где T является переменным полем и Tlambda - скалярное значение, определенное во время выполнения.

+0

Пожалуйста, разместите код, в котором вы берете энергию и сохраняете ее в стеке. – UsamaMan

+2

Рассмотрите возможность использования библиотеки [GMP library] (https://gmplib.org/) для больших чисел. –

+0

Я редактирую свой комментарий. Я проверил библиотеки, скомпилированные с программным обеспечением, и GMP-5.1.2 установлен, поэтому я думаю, что проблема возникает в другом месте. – SimoMJ

ответ

0

A double Переменная, вероятно, также не может содержать 19 нулей. A (десятичная) цифра принимает более 3 бит, поэтому 19 нулей будут занимать не менее 57 бит. A double обычно имеет мантисс, который составляет всего 53 бит.

Однако это не похоже на проблему, которая у вас есть. В C++ код, выражения также имеют тип. 1 - это не то же самое, что и 1.0. Первый - это int, а второй - double. Хотя вы можете конвертировать int в double, они не совпадают. Вероятно, int может содержать значения до 2 миллиардов, но формально он может иметь ограничение до 32767. Решение вашей проблемы может быть таким же простым, как добавление двадцатого ноль: 100000000000000000000.0, что делает его double.

+0

Наконец-то выяснилось, что ошибка исходила от повышения отрицательной базы до показателя мощности, используя pow(). Если база является конечной отрицательной, а показатель степени конечен, но не является целочисленным значением, это вызывает ошибку домена. Я разобрался с некоторыми функциями, используя функцию знака. Однако ваше решение было полезным, так как оно решило еще одну ошибку, которую я имел в коде при вводе больших целых значений. Так что спасибо тебе ! – SimoMJ

+0

@SimoMJ Этого следовало ожидать. 'pow (-1, 0, .5)' должно быть '0 + 1i', но' pow' не возвращает комплексные числа. – MSalters

+0

Да и правда. Одно из моих граничных условий не было установлено должным образом и заставляло ценности расходиться в какой-то момент, что сделало базовую мощность отрицательной, теперь я решил эту проблему, но большое спасибо всем за ваши предложения. – SimoMJ

 Смежные вопросы

  • Нет связанных вопросов^_^