![]() |
|
Модераторы: Partizan, gambit |
![]()
|
|
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
Привет, All =)
в общем вот есть код с комментариями:
Кто что об этом думает? -------------------- СУВ, Partizan. |
|||
|
||||
| archeg |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 612 Регистрация: 6.1.2007 Где: Киев Репутация: 11 Всего: 27 |
Интерестный вопрос. Вот код класса ValueType (род. класс структуры):
Прошелся дебаггером - фолс возвращает в месте где вызываеться CanCompareBits а затем FastEqualsCheck. К несчастью оба метода имеют анменейдж реализацию, и я неуверен что они делают - мое предположоние, судя по названию, просто сравнивают биты структур в памяти. Если руководиться этим выходит что при double a = 0.0; и double b = -0.0; а и b имеют одинаковое значение, но не одинаковые внутренние поля (например, кажись там есть поле _isNegative или что-то подобное) - а поэтому сравнивание происходит не так как бы хотелось. Надеюсь что прав. Если есть мастера у которых другой ответ - образумьте -------------------- ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru) Дядька всегда можно спросить в аське, если не задалбывать - не откажет И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои ;) |
|||
|
||||
| jonie |
|
|||
|
Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 5613 Регистрация: 21.8.2005 Где: Владимир Репутация: 22 Всего: 118 |
на самом деле хуже то что true выдается...
вообще он и не должен как раз появляться, числа 0.0 и -0.0 это разные числа... подробне можно найти в IEEE чета там, про машинное представление числа в общем....
-------------------- Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет... |
|||
|
||||
| archeg |
|
||||||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 612 Регистрация: 6.1.2007 Где: Киев Репутация: 11 Всего: 27 |
Точно. Как-то в эту сторону не подумал Спецификация double (IEEE 754) Только видать .нет при обработке Equals игнорирует разницу, ибо:
Выдаст true ;) Что в общем правильно. Только в памяти то они разные. -0 = 1 11111111 00000000000000000000000 0 = 0 11111111 00000000000000000000000 Поэтому во-втором случае еквалс таких структур возвращает false. В первом случае, оно почему-то решает что существуют ссылки из GC в структуре и поэтому отказываеться от сравнения по битам, а сравнивает по полям - что призводит к ответу в true -------------------- ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru) Дядька всегда можно спросить в аське, если не задалбывать - не откажет И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои ;) |
||||||
|
|||||||
| nikitao |
|
|||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 4 Всего: 26 |
идиотизм. от такого бага можно в психушку попасть , прежде чем поймешь в чем дело.
-------------------- Жизнь - печальная штука. |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
||||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
Итак, есть люди, которые могут до конца прояснить логику такого неоднозначного поведения?
-------------------- СУВ, Partizan. |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
Вот - нашел - всетаки в стандарте это есть: C# supports two floating-point types: float and double. The float and double types are represented using the 32-bit single-precision and 64-bit double-precision IEC 60559 formats, which provide the following sets of values: • Positive zero and negative zero. In most situations, positive zero and negative zero behave identically as the simple value zero, but certain operations distinguish between the two (§14.7.2). • Positive infinity and negative infinity. Infinities are produced by such operations as dividing a non-zero number by zero. [Example: 1.0 / 0.0 yields positive infinity, and –1.0 / 0.0 yields negative infinity. end example] • The Not-a-Number value, often abbreviated NaN. NaNs are produced by invalid floating-point operations, such as dividing zero by zero. • The finite set of non-zero values of the form s × m × 2e, where s is 1 or −1, and m and e are determined by the particular floating-point type: For float, 0 < m < 224 and −149 ≤ e ≤ 104, and for double, 0 < m < 253 and −1075 ≤ e ≤ 970. Denormalized floating-point numbers are considered valid non-zero values. C# neither requires nor forbids that a conforming implementation support denormalized floatingpoint numbers. Т.е. для float и для double есть константные значение +0 и -0. Добавлено через 2 минуты и 35 секунд Стандарт всетаки великая вещь, я вчера пытался в нем выискать особенности работы Equals для double - ничего не нашел, подумал что это какая-то недокументированная особенность. А сегодня посмотрел описалово double - в первой же строке объяснение |
|||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
HalkaR, ненененене )
мне не понятна другая вещь) почему в первом случае 0.0 и -0.0 при сравнении структур воспринимаются как равные, а во втором - как отличные друг от друга? ведь по сути операция - одна и та же... вызывается Equals для ValueType... -------------------- СУВ, Partizan. |
|||
|
||||
| archeg |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 612 Регистрация: 6.1.2007 Где: Киев Репутация: 11 Всего: 27 |
ОК. Где бы взять код анменейдж методов CanCompareBits и FastEqualsCheck ?
Проблема именно в них. Все другое работает правильно
Инт не отличает -0 от 0. В памяти и то и то выглядит как 000000.... Походу -0 и 0 есть только в double и float Это сообщение отредактировал(а) archeg - 7.10.2008, 11:56 -------------------- ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru) Дядька всегда можно спросить в аське, если не задалбывать - не откажет И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои ;) |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
|
|||
|
||||
| archeg |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 612 Регистрация: 6.1.2007 Где: Киев Репутация: 11 Всего: 27 |
Если бы все было так просто, тогда почему же в 1-м случае результат true? В первом те же даблы с +0 и -0 -------------------- ИМХО задница есть универсальный интерфейс. Ибо через задницу можно сделать абсолютно ВСЕ (bash.org.ru) Дядька всегда можно спросить в аське, если не задалбывать - не откажет И вообще, на самом деле я студент, и ненавижу обращение на "Вы") Тут все свои ;) |
|||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
HalkaR, а какая разница? переменные, хранящие 0.0 и -0.0 в обоих структурах (и D1, и D2) имеют тип double
-------------------- СУВ, Partizan. |
|||
|
||||
| HalkaR |
|
||||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
Partizan, еще раз повторяю - это для тебя -0 и +0 это одно и тоже. Для типа double в C# -0 - это специальная константа, которая хранится в памяти не как 0.
Добавлено через 42 секунды То, что при отладке студия показывает значение это константы как 0 - ничего не значит - во внутреннем представлении double - это не тоже самое что 0. Добавлено через 1 минуту и 47 секунд
Мда.. тут пока загадка. Добавлено через 2 минуты и 5 секунд
Хм, еще непонятно. |
||||
|
|||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
HalkaR, да для меня +0.0 и -0.0 - это тоже разные вещи....я просто не понимаю, почему в одном случае Equals их воспринимает как одинаковые, а в другом - нет...
Добавлено через 1 минуту и 20 секунд кстати разведка доложила, что жаба в обоих случаях возвращает false. -------------------- СУВ, Partizan. |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
Partizan, есть предположение, что для D1 метод CanCompareBits возвращает false по причине наличия поля типа int и сравнение ведется не побитиво, а по полям. А в D2 выполняется FastEqualsCheck, который возвращает false.
|
|||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
ммм...странно..очень странно...каким образом поле типа int может повлиять на возможность побитового сравнения?
-------------------- СУВ, Partizan. |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
Копание в инете дало варианта - CanCompareBits не проходит если в структуре есть пропуски, которые забиваются случайными данными. Возможно то как раз тот случай.
|
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
||||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
мде...вот и ответ на вопрос...
Magic???? - Magic! -------------------- СУВ, Partizan. |
|||
|
||||
| nikitao |
|
|||
![]() Кот-программист ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1206 Регистрация: 30.8.2005 Где: Спб Репутация: 4 Всего: 26 |
Если я все правельно понял , то получается следующее :
1. В памяти +0 и -0 хранятся по разному , для вещественных типов 2. Разработчики BCL определили Equals для вещественных чисел таким образом , что +0 -0 равные числа. Обоснование этого - для человека это действительно одинаковые числа. В общем то так оно и должно быть. 3. Для типов значений метод Equals без переопределения исходя из каких то своих соображений то выдает результат на основе побитового сравнения обьектов , то сравнивая поля класса. 4. Из-за переопределённого на уровне double Equals метода мы получаем разные результаты при разных способах сравнения обьектов. Просто разработчики BCL видемо забыли такой вариант рассмотреть. Не знаю , по идее надо куда то писать в M$ с просьбой профиксить. Интересно все таки на основе чего выбирается метода сравнения валуе типов..... Кто нибудь проверял это в CLR 1.x. вдруг там подругому.... Это сообщение отредактировал(а) nikitao - 7.10.2008, 19:53 -------------------- Жизнь - печальная штука. |
|||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
Проверяли в жабе...в обоих случаях она выдаёт false
-------------------- СУВ, Partizan. |
|||
|
||||
| diadiavova |
|
|||
![]() Доктор Зло(диагност, настоящий, с лицензией и полномочиями) ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5821 Регистрация: 14.8.2008 Где: В Коньфпольте Репутация: 31 Всего: 142 |
А ты добавь в структуру D2 поле типа int, можешь даже не делать с ним ничего, и посмотри результат.
-------------------- Хочешь получить мудрый совет - читай подписи участников форумов. Злой доктор Щасзаболит |
|||
|
||||
| HalkaR |
|
|||
![]() Пуфыстый назгул ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 2132 Регистрация: 8.12.2002 Где: В Москве Репутация: 14 Всего: 42 |
diadiavova, собственно в результате никто не сомневается
|
|||
|
||||
| Дрон |
|
|||
![]() Java-ненавистник :) ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 3179 Регистрация: 29.12.2002 Где: Санкт-Петербург Репутация: 24 Всего: 93 |
Прикольный баг. Надо всё-таки самим определять Equals, а не надеятся на компилятор.
Извиняюсь, а как такое можно проверить в Java, если там в принципе нет никаких value type? -------------------- Да. Именно так. |
|||
|
||||
| Partizan |
|
|||
![]() Let's do some .NET ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 2828 Регистрация: 19.12.2005 Где: Санкт-Петербург Репутация: 18 Всего: 67 |
Дрон, =) Не знал, не спец по жабе) я ж говорю, разведка доложила)
-------------------- СУВ, Partizan. |
|||
|
||||
| diadiavova |
|
|||
![]() Доктор Зло(диагност, настоящий, с лицензией и полномочиями) ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 5821 Регистрация: 14.8.2008 Где: В Коньфпольте Репутация: 31 Всего: 142 |
Честно говоря всю тему поленился читать, каюсь. Выскажу предположение, надеюсь меня за это не побьют. Когда в структуре числовые поля одного типа, их сравнение ведётся по упрощённому алгоритму, просто сравниваются как double и всё. А если поля разнотипные, то сначала проверяется тип, причём проверка осуществляется по значению. При проверке чисел 0 и -0 они(по значению) типизируются как целочисленные и логика перенаправляется в ту ветвь, где сравниваются целые числа. А при сравнении их как целых результат очевиден. Так что, возможно это не ошибка, а просто ради экономии ресурсов упростили. -------------------- Хочешь получить мудрый совет - читай подписи участников форумов. Злой доктор Щасзаболит |
|||
|
||||
| source777 |
|
|||
![]() Эксперт ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 1878 Регистрация: 12.3.2007 Репутация: 4 Всего: 56 |
здравая мысль.
Впрочем это как раз будет следованием .NET Guidelines.. Все сравниваемые пользовательские типы должны иметь собственную реализацию IEquatable<T>. -------------------- Если бы программистам платили за то, чтобы убирать код из программы вместо того, чтобы добавлять его, программы были бы намного лучше © Николас Негропонте |
|||
|
||||
![]()
|
| Прежде чем создать тему, посмотрите сюда: | |
|
|
Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов. Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :) Так же не забывайте отмечать свой вопрос решенным, если он таковым является :) Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |