0x01AA Ответов: 2

C# деление на ноль для двойников-comvisible-infinity vs. Исключение dividebyzeroexception


Уважаемые Эксперты
У меня есть сборка .net COMVisible, которая выполняет некоторые вычисления с двойными числами, а также деления. Итак, допустим, дело доходит до такой ситуации:
double a= 250.0;
double b= 0.0;
double c= a / b;

а) использование сборки из приложения .net
В этом случае результат деления похож на ожидаемый
c= Infinity;

б) использование _одинаковый_ сборка по COM из собственного приложения W32
В этом случае деление приводит к
DivideByZeroException


[Edit0]это происходит также только в том случае, если происходит внутренняя сборка x/0.0, без возврата (маршалинга) этого результата обратно в W32. [/Edit0]
[Edit1]некоторая предыстория, почему это меня беспокоит: мы пытаемся шаг за шагом перейти от W32 к .NET. В промежуточном временном интервале мы хотели бы использовать новые сборки .NET также в устаревшем приложении [/Edit1]

Во-первых, это было очень удивительно для меня, но я могу понять, что это, возможно, связано с W32 - "хостом".

Вопрос: есть ли у кого-нибудь идея позволить вести себя сборке всегда одинаково, желательно, чтобы деление на 0.0 дало результат Infinity?

Заранее большое вам спасибо за некоторые подсказки.

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

Много гуглил, но безуспешно.

F-ES Sitecore

То, что делится на ноль, не является бесконечностью, поэтому результат правильный. Если вы хотите, чтобы деление на ноль вернуло что-то конкретное, вам нужно будет встроить это в код

если (b = = 0)
return customValue
еще
возврат a/b

0x01AA

- Нет, извини. По определению в c# деление x/0.0 заканчивается на бесконечность / NaN. Я в порядке с этим, но что меня беспокоит, так это то, что в случае, если я использую сборку .net из приложения .net, это похоже на это, но когда я использую _same_assembly by COM, он выдает исключение :(

И нет, я никогда не проверю b==0.0, потому что подобное может произойти, если a очень большой (например, Макс двойной) и b= 10E-127

F-ES Sitecore

Я никогда не знал, что c# не бросает ошибку деления на ноль.

0x01AA

Это так для double, но не для int или Decimal
В любом случае, спасибо за ВАШ интерес к этому вопросу.

Кроме того, это в c# не вызывает исключения (за исключением случаев, используемых COM):
двойной a = двойной.Максвеллову;
двойной b = 1.0 / a;
двойной c = a / b;

F-ES Sitecore

Только что проверил, и вы правы, я, очевидно, не очень часто использовал двойники :)

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

0x01AA

Это также не является вещью упорядочивания. На данный момент x/0.0 не возвращается в приложение W32, это только промежуточный результат... который в конечном итоге заканчивается com-исключением из представления приложения W32 :-)

Richard MacCutchan

Попробуйте мой пример кода ниже.

0x01AA

Да, это действительно подтверждает, что c# не исключение. С, D, Е все имеют значение Infinity.
Спасибо, Бруно

Richard Deeming

Может быть, это флаги с плавающей запятой в вызывающем приложении?

Двойное деление на ноль возвращает ошибку деления на ноль[^]
(Не совсем то же самое, что и ваша проблема, но звучит похоже.)

0x01AA

Просто проверить. Это действительно работает (означает, что div по нулевым результатам теперь находится в бесконечности) на первый взгляд, если я позвоню, например
_clearfp();
Функции _fpreset();
в конструкторе видимой сборки COM. Пока все идет хорошо, теперь мне нужно проверить, как это влияет на мое приложение W32 :)

Большое вам спасибо за этот намек!

И если вы опубликуете его в качестве ответа, я приму его, даже если он не решит мою проблему, но ответит на мой вопрос :-)
Еще раз большое вам спасибо.
Бруно

2 Ответов

Рейтинг:
1

Patrice T

DivideByZeroException это стандартное поведение во всех компьютерах.
Ваш результат ".net COMVisible" исходит из обработки исключения и infinity это искусственный результат, выталкиваемый обработчиком исключений.

То DivideByZeroException это оправдано, потому что многие правила могут применяться, и все они приводят к разным результатам:
- Все, что делится само по себе, приводит к 1: 1/1=1, а почему не 0/0=1 ?
- Ноль, деленный на что угодно, приводит к 0: 0/1=0, а почему бы и не 0/0=0 ?
- Все, что делится на очень малую величину, приводит к большой величине, доведенной до крайности, ведет к бесконечности.
Какой ответ правильный?

Цитата:
Есть ли у кого-нибудь идея позволить вести себя сборке всегда одинаково, предпочтительно чтобы деление на 0.0 дало результат Бесконечности?

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


0x01AA

Извините, нет, это совершенно неправильно: "DivideByZeroException-это стандартное поведение на всех компьютерах."

В c# для типа double (обратите внимание, что он отличается для int / Decimal)определено, что x/0.0 не вызывает исключения.

А 3 оставаться нейтральным ;)

Patrice T

Я в порядке с нейтральным 3.
Должен ли я был сказать процессор вместо компьютера ?

0x01AA

Я думаю, что оба они ошибаются. Fpu осознает NaN / Infinity, ... То, что я пытаюсь сказать: также в родном языке, например c++, вы можете контролировать, что x/0.0 не закончится исключением. Но я думаю, что из истории это первый выбор, чтобы бросить исключение.

0x01AA

Я думаю, что оба не правы. Математический процессор (fpu) действительно знает NaN и бесконечность. Значит, и для нативных приложений можно управлять поведением fpu, а не выбрасывать исключение и вместо этого возвращать Infinity/NaN

0x01AA

Дело в том, что при голосовании 3: я предполагаю, что вы тем временем знаете, как я голосую. Кроме того, особенно для моих собственных вопросов: если кто-то серьезно попытается помочь (как это сделали вы) Я бы никогда не опустился ниже 3, даже ответ не правильный.
Бруно

Рейтинг:
1

Richard MacCutchan

Нет никакого способа представить Infinity или NaN в Win32 таким образом вы получаете ошибку разделения, которая является правильным ответом. C# делает вид, что существует реальный результат от такого разделения просто как ярлык. Но разработчику все равно нужно проверить его; например, какие значения вы ожидаете получить? d и e в следующем коде?

double a = 1.0;
double b = 0.0;
double c = a / b;
double d = c * 2.0;
double e = c / 5.0;


0x01AA

"Нет никакого способа представить бесконечность или NaN в Win32 "
- Пожалуйста. Бесконечность и NaN определяются IEEE-754, также доступными в W32, если установить поведение с плавающей запятой.

Richard MacCutchan

Это искусственные идентификаторы, которые могут быть возвращены при возникновении исключения. И как я уже сказал, Если вы не получите исключения, то ваше заявление может с радостью продолжаться в таком случае, как описано выше, и никто ничего не узнает; что действительно глупо.

0x01AA

Ричард
а) стандартное поведение .net - x/0.0 дает результат Бесконечности. Это очень хорошо.

б) в случае, если я использую сборку .net, которая _internal_ вычисляет x/0.0, заканчивается исключением в .net и, наконец, исключением DCOM. Чтобы было более понятно (нужно улучшить мой вопрос), Бесконечность не планируется возвращать W32.

Этот факт очень и очень сложен в случае, если вам нужно шаг за шагом перейти с W32 на .net :-)

Большое спасибо за ВАШ интерес к этому вопросу.

Richard MacCutchan

а) я не согласен. Просто посмотрите на некоторые ленивые вопросы здесь, в QA. Мой пример кода показывает, почему отсутствие исключения-плохая идея. Программисты не будут тестировать его, и их приложения создадут хаос. На самом деле я подозреваю, что некоторые уже делают это.
Б) (и а) наличие исключения сразу же говорит вам, что что-то не так, и вы можете что-то сделать, чтобы это исправить. Или, по крайней мере, сообщить об этом пользователю.

0x01AA

Опять же: c# _does not_ бросает исключение, и это _is_ стандартное поведение c# (.net?), за исключением того, что вы меняете настройки fp.

Richard MacCutchan

а) я не согласен. Просто посмотрите на ленивый вопрос здесь, в QA. Мой пример кода показывает, почему отсутствие исключения-плохая идея. Программисты не будут тестировать его, и их приложения создадут хаос. На самом деле я подозреваю, что некоторые уже делают это.
Б) (и а) наличие исключения сразу же говорит вам, что что-то не так, и вы можете что-то сделать, чтобы это исправить. Или, по крайней мере, сообщить об этом пользователю.

0x01AA

Опять же: c# в своем стандартном поведении не создает исключения для x/0.0. Это независимо от того, согласны вы или нет, определяется MS таким образом. И да, можно изменить стандартное поведение, манипулируя вычислением fp, что, по-моему, очень плохая идея, чтобы оставаться совместимым.

Richard MacCutchan

Согласованный.

0x01AA

Вас трудно убедить :-)
Спасибо за интерес и вашу помощь.


Кстати: похоже, вы столкнулись с той же проблемой, что и я, когда писали комментарий. Извините за "двойные посты комментариев", но это, кажется, вещь CP.

Richard MacCutchan

Все в порядке, меня не в чем убеждать. Мы можем соглашаться или не соглашаться, это одна из радостей дискуссионного форума.

Вчера я не заметил двойного столба, может быть, неприятности с пальцами.