Optimistic76 Ответов: 3

Двойная операция C++ дает разный результат в разных условиях


доброе утро,

Я разработал библиотеку DLL Vc++, вызванную программой VB. DLL имеет функцию, которая выполняет некоторую операцию над векторами точек (double[3])

теперь предположим, что у нас есть два набора точек S, T.

Если программа Vb вызывает функцию только один раз с набором точек T, я получаю результат.
Если программа Vb вызывает функцию два раза, сначала с набором S, а затем с набором T, то результат для набора T отличается от предыдущего.

Я пытаюсь отладить, и разница - это продукт двух двойников, которые действуют по-разному.
У меня есть два двойных dx и dy и эта функция работает:

dx2 = dx*dx
dy2 = dy*dy

с помощью отладочных строк я получаю:

если я звоню только Set T я получаю
[2920]point 10-->   dx: 32951.71011630935400000000 dy: 1784.60091076856500000000 dx2: 1085815199.58928420000000000000 dy2:3184800.41071599160000000000 A:1089000000.00000020000000000000   B:0.00065903420232618713  C:-272250000.00000000000000000000  



со звонком с набором т после звонка с установить s:
[2920]<pre>point 10-->   dx: 32951.71011630935400000000 dy: 1784.60091076856500000000 dx2: 1085815199.58928390000000000000 dy2:3184800.41071599160000000000 A:1089000000.00000000000000000000   B:0.00065903420232618702  C:-272250000.00000000000000000000  



как вы можете видеть, dx одинаков для обоих вызовов, но resut dx2 отличается.
в конечном результате разница накапливается для всех точек, и я получаю слегка различное значение.

Кто-нибудь имеет представление о том, что здесь происходит?
Кажется, что после первого вызова функция находится в другом состоянии, но как это может повлиять на продукт с теми же операндами?
спасибо

Что я уже пробовал:

Я попытался проверить, нет ли утечки памяти, но не увидел ничего странного.

Kornfeld Eliyahu Peter

Возможно, у вас есть какие-то глобальные переменные для хранения состояния?
Просмотр вашего кода может помочь нам помочь вам...

Richard MacCutchan

Не видя вашего кода, трудно догадаться, что происходит.

3 Ответов

Рейтинг:
11

Optimistic76

Ну, чтобы заставить его работать, мне пришлось вызвать _fpreset () в начале функции.
Что-то в компоненте, который вызывает мою библиотеку, изменяет состояние единицы измерения с плавающей запятой, но это все еще странно, потому что я проверил значение с помощью _controlfp, и глобальное значение изменилось, но не режим округления.

ОБНОВЛЕНИЕ:

Я проверил лучше, и то, что изменилось, - это значение точности. Я думаю, что это действительно может повлиять на результаты округления.


[no name]

Это должно было быть добавлено к вопросу, чтобы на него можно было ответить соответствующим образом. Похоже, вы восстановили FPU до его стандартной (двойной) точности. Какая функция устанавливает его в одиночное положение? Разве вы не контролируете этот код, как следует из вашего вопроса?

Optimistic76

К сожалению, у меня нет контроля над компонентом, который вызывает мою библиотеку. Я мог проверить значение только в начале вызова функции. Но я могу только догадываться, что, возможно, явный _controlfp в исходном коде изменяет точность FPU.

Рейтинг:
1

User 59241

Двойник не даст вам бесконечной точности-никогда. Это указывает на то, почему математические вычисления с использованием C++, неправильные ответы - переполнение стека[^]
32951.71011630935400000000, вероятно, не может быть представлен в двоичном виде, так что есть проблема с самого начала, как и результат.
Сделайте расчет здесь Высокоточный калькулятор[^] и вы получите 1085815199.589284220118545827897316
Почему ваш код ведет себя именно так, можно определить, только наблюдая за ходом выполнения.
Если вы хотите использовать очень высокую точность в численных расчетах, вам нужно будет посмотреть на что-то вроде Библиотека GNU MP Bignum[^]


Рейтинг:
0

KarstenK

Распространенной проблемой является то, что двойные значения могут незначительно отличаться в зависимости от потока операций. Вы уверены, что вход действительно один и тот же? Обычно вы избегаете этой проблемы, допуская некоторые различия.

Любые математические вычисления лучше выполнять на более быстром и точном языке C++.
В противном случае вы должны подумать об использовании другого представления ваших ценностей.

Используйте опцию "Strict" в VB.


0x01AA

К вашему сведению: сделал незначительную поправку issuerthat вопрос В. Что ;)

[no name]

ОП-это уже вызов функции в DLL-библиотеки C++, чтобы сделать расчет.