(double)0.001f = 0.0010000000474974513. Почему???
От: barn_czn  
Дата: 13.01.10 04:22
Оценка:
Собственно сабж.
Народ, может мне ктонить ответить мочему так работает приведение.
У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
Вопрос — почему шумом а не нулями?
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: Аноним  
Дата: 13.01.10 04:35
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?

попытайся записать 1/1000 в двоичной системе исчесления.
И почитай википедию
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: LaptevVV Россия  
Дата: 13.01.10 04:37
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?
Дык попробуй сам вручную перевести 0.001 из десятичной в двоичную. А потом обратно. И помедитируй над результатами.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 13.01.10 04:39
Оценка: 1 (1) +3
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?

Блин, ну внесите уже этот вопрос в FAQ — ей-богу, каждый месяц его задают!
[КУ] оккупировала армия.
Re[2]: C# - идея расширения для where - новое ограничение дл
От: barn_czn  
Дата: 13.01.10 04:53
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, barn_czn, Вы писали:


_>>Собственно сабж.

_>>Народ, может мне ктонить ответить мочему так работает приведение.
_>>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>>Вопрос — почему шумом а не нулями?
LVV>Дык попробуй сам вручную перевести 0.001 из десятичной в двоичную. А потом обратно. И помедитируй над результатами.

Не понимаю.

0.001 = 1 * 10^-3, т.е.

Мантиса = 000...0001
Степень = +1 (знак "-") 000..100

Ну как так, кол-во нулей не важно.
Где здесь бесконечная периодическая двоичная запись?
Re[2]: C# - идея расширения для where - новое ограничение дл
От: barn_czn  
Дата: 13.01.10 05:08
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, barn_czn, Вы писали:


_>>Собственно сабж.

_>>Народ, может мне ктонить ответить мочему так работает приведение.
_>>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>>Вопрос — почему шумом а не нулями?

А>попытайся записать 1/1000 в двоичной системе исчесления.

А>И почитай википедию

В википедии говорится о какой то периодической двоичной записи для 0.1 Откуда она берется — не понимаю.

Но дело ведь не в представлении таких чисел, а преобразовании типов.
Создать переменную float f = 0.001f я могу, double d = 0.001 — тоже могу. Какова ж черта d != (double)f ?
Re[3]: C# - идея расширения для where - новое ограничение дл
От: _FRED_ Черногория
Дата: 13.01.10 06:04
Оценка: +1
Здравствуйте, barn_czn, Вы писали:

_>>>Народ, может мне ктонить ответить мочему так работает приведение.

_>>>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>>>Вопрос — почему шумом а не нулями?
LVV>>Дык попробуй сам вручную перевести 0.001 из десятичной в двоичную. А потом обратно. И помедитируй над результатами.
_>Не понимаю.
_>0.001 = 1 * 10^-3, т.е.
_>Мантиса = 000...0001
_>Степень = +1 (знак "-") 000..100
_>Ну как так, кол-во нулей не важно.
_>Где здесь бесконечная периодическая двоичная запись?

Попробуйте прочитать вдобавок Плавающая запятая
Автор(ы): Сергей Холодилов
Дата: 15.03.2008
Если яблоко поровну разделить на троих, каждому достанется треть. Так в нашу жизнь входят дроби, примерно с теми же целями входят они и в программирование.. Но реализация дробей в виде типов данных float/double ведёт себя не совсем "математично". В чём причина отличий, как минимизировать их влияние на результат вычислений, как же всё это всё-таки реализовано и почему запятая плавает — читайте в статье.
.

По сути — в представлении double и float основание степени не десять как у вы считаете ("0.001 = 1 * 10^-3") а два Попробуйте отыскать такие q и M что бы 0.001 = M * 2 ^ q.
А вот в Systen.Decimal одна тысячная представима как нельзя лучше. Там основание 10.
Help will always be given at Hogwarts to those who ask for it.
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: Аноним  
Дата: 13.01.10 06:26
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?

Все зависит от компилятора!!! При приведении типа часть компиляторов просто копирует кусок памяти меньшего размера (float) в больший (doudle). Все что было больше размера меньшего операнда остается. Собственно если сначала обнулить doudle то все будет как надо.
Re[2]: (double)0.001f = 0.0010000000474974513. Почему???
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.01.10 06:46
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, barn_czn, Вы писали:


А>Все зависит от компилятора!!! При приведении типа часть компиляторов просто копирует кусок памяти меньшего размера (float) в больший (doudle). Все что было больше размера меньшего операнда остается.

И порядок float-а плавно переходит в мантиссу double-а... Браво!

A> Собственно если сначала обнулить doudle то все будет как надо.

И на каких компиляторах работает "как надо"?
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: Severn Россия  
Дата: 13.01.10 07:34
Оценка: 16 (1)
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?

Is there such a thing as too much precision?
Re[3]: (double)0.001f = 0.0010000000474974513. Почему???
От: venicum Россия -
Дата: 13.01.10 07:36
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Но дело ведь не в представлении таких чисел, а преобразовании типов.

_>Создать переменную float f = 0.001f я могу, double d = 0.001 — тоже могу. Какова ж черта d != (double)f ?

Честно, после того когда давненько прочитал стандарты IEEE, меня такое не удивляет.
p.s.
В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять
является ли модуль разности менее какой-либо точности, определенной для данной задачи.
Re[4]: C# - идея расширения для where - новое ограничение дл
От: barn_czn  
Дата: 13.01.10 08:31
Оценка:
Здравствуйте, venicum, Вы писали:

V>Здравствуйте, barn_czn, Вы писали:


_>>Но дело ведь не в представлении таких чисел, а преобразовании типов.

_>>Создать переменную float f = 0.001f я могу, double d = 0.001 — тоже могу. Какова ж черта d != (double)f ?

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

V>p.s.
V>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять
V>является ли модуль разности менее какой-либо точности, определенной для данной задачи.

Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.
Я просто довел реальную ситуацию до абсурда, чтобы пример проще был.

А реальная проблема вот в чем. Некий метод делает вычисления на float-ах. Далее результат этого метода попадает в другой метод где уже вычисления ведутся на double, т.е. входные данные — аргумент double. А в результате такова кривого приведения получается что входные данные с ошибкой пришли.

И это мне очень не нравится. Победил пока это двойным приведением (double)(decimal)f. Костыль конечно, но работает.
Re[3]: C# - идея расширения для where - новое ограничение дл
От: barn_czn  
Дата: 13.01.10 08:34
Оценка:
Здравствуйте, samius, Вы писали:

S>Здравствуйте, Аноним, Вы писали:


А>>Здравствуйте, barn_czn, Вы писали:


А>>Все зависит от компилятора!!! При приведении типа часть компиляторов просто копирует кусок памяти меньшего размера (float) в больший (doudle). Все что было больше размера меньшего операнда остается.

S>И порядок float-а плавно переходит в мантиссу double-а... Браво!

Вы утрируете по моему. Мантиса должна перейти в мантису, показатель в показатель.. Если все корректно делать то не будет никакова шума , я так и не понимаю в чем сложность, но почему то этого нет.
Re[5]: C# - идея расширения для where - новое ограничение дл
От: _FRED_ Черногория
Дата: 13.01.10 09:10
Оценка: -1
Здравствуйте, barn_czn, Вы писали:

V>>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять

V>>является ли модуль разности менее какой-либо точности, определенной для данной задачи.

_>Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.


Оба утверждения неверны. Что "не так" в следующем сравнении:
var d1 = 2.2 / 3.3;
var d2 = 4.4 / 6.6;
Debug.Assert(d1 == d2, "d1 == d2");

Сравнивать нужно аккуратно, да, понимая что делаешь. Но можно.
Help will always be given at Hogwarts to those who ask for it.
Re[6]: C# - идея расширения для where - новое ограничение дл
От: _FRED_ Черногория
Дата: 13.01.10 09:15
Оценка:
Здравствуйте, _FRED_, Вы писали:

V>>>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять

V>>>является ли модуль разности менее какой-либо точности, определенной для данной задачи.
_>>Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.

_FR>Оба утверждения неверны. Что "не так" в следующем сравнении:

_FR>var d1 = 2.2 / 3.3;
_FR>var d2 = 4.4 / 6.6;
_FR>Debug.Assert(d1 == d2, "d1 == d2");

_FR>Сравнивать нужно аккуратно, да, понимая что делаешь. Но можно.

Таки отыскал ссылку на "ликбез": Re[2]: memcmp и float
Автор: McSeem2
Дата: 31.08.07
Help will always be given at Hogwarts to those who ask for it.
Re[4]: C# - идея расширения для where - новое ограничение дл
От: samius Япония http://sams-tricks.blogspot.com
Дата: 13.01.10 09:42
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Здравствуйте, samius, Вы писали:


S>>Здравствуйте, Аноним, Вы писали:


А>>>Здравствуйте, barn_czn, Вы писали:


А>>>Все зависит от компилятора!!! При приведении типа часть компиляторов просто копирует кусок памяти меньшего размера (float) в больший (doudle). Все что было больше размера меньшего операнда остается.

S>>И порядок float-а плавно переходит в мантиссу double-а... Браво!

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


Это не моя идея, а Аноним-а, см. выделенное.
Re[6]: C# - идея расширения для where - новое ограничение дл
От: venicum Россия -
Дата: 18.01.10 17:26
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, barn_czn, Вы писали:


V>>>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять

V>>>является ли модуль разности менее какой-либо точности, определенной для данной задачи.

_>>Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.


_FR>Оба утверждения неверны. Что "не так" в следующем сравнении:

_FR>
_FR>var d1 = 2.2 / 3.3;
_FR>var d2 = 4.4 / 6.6;
_FR>Debug.Assert(d1 == d2, "d1 == d2");
_FR>

_FR>Сравнивать нужно аккуратно, да, понимая что делаешь. Но можно.

Что не так в следующем сравнении:
_FR>
_FR>var d1 = 11 / 3.3;
_FR>var d2 = 33 / 9.9;
_FR>Debug.Assert(d1 == d2, "d1 == d2");
_FR>
Re[7]: C# - идея расширения для where - новое ограничение дл
От: _FRED_ Черногория
Дата: 18.01.10 17:57
Оценка:
Здравствуйте, venicum, Вы писали:

V>>>>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять

V>>>>является ли модуль разности менее какой-либо точности, определенной для данной задачи.
_>>>Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.
_FR>>Оба утверждения неверны. Что "не так" в следующем сравнении:
_FR>>var d1 = 2.2 / 3.3;
_FR>>var d2 = 4.4 / 6.6;
_FR>>Debug.Assert(d1 == d2, "d1 == d2");

_FR>>Сравнивать нужно аккуратно, да, понимая что делаешь. Но можно.

V>Что не так в следующем сравнении:

V>var d1 = 11 / 3.3;
V>var d2 = 33 / 9.9;
V>Debug.Assert(d1 == d2, "d1 == d2");


Ты бы хоть показал что изменил, убрав мои цитаты.
Твой ответ не даёт ответ на мой вопрос: Ну и что же "не так" в моём сравнении?
Help will always be given at Hogwarts to those who ask for it.
Re[8]: C# - идея расширения для where - новое ограничение дл
От: venicum Россия -
Дата: 18.01.10 20:25
Оценка:
Здравствуйте, _FRED_, Вы писали:

_FR>Здравствуйте, venicum, Вы писали:


V>>>>>В принципе при сравнении двух дробных чисел нельзя использовать явную проверку на равенство, нужно проверять

V>>>>>является ли модуль разности менее какой-либо точности, определенной для данной задачи.
_>>>>Про сравнение согласен, если в коде есть сравнение двух плавающих — тут явно чтото не так.
_FR>>>Оба утверждения неверны. Что "не так" в следующем сравнении:
_FR>
_FR>>>var d1 = 2.2 / 3.3;
_FR>>>var d2 = 4.4 / 6.6;
_FR>>>Debug.Assert(d1 == d2, "d1 == d2");
_FR>

_FR>>>Сравнивать нужно аккуратно, да, понимая что делаешь. Но можно.

V>>Что не так в следующем сравнении:

_FR>
_FR>V>var d1 = 11 / 3.3;
_FR>V>var d2 = 33 / 9.9;
_FR>V>Debug.Assert(d1 == d2, "d1 == d2");
_FR>


_FR>Ты бы хоть показал что изменил, убрав мои цитаты.

_FR>Твой ответ не даёт ответ на мой вопрос: Ну и что же "не так" в моём сравнении?

Вы бы посмотрели на цифры, ввели бы код в VS200>=8.
Я не сказал, что ваш пример не верен, я также не говорил в своем посте, что сравнивать числа с плавающей точкой явно нельзя.
('В принципе' — вводная конструкция, выражает степень не уверенности. Извините, что не обособил с обеих сторон.)
Мой пример показывает, что такое сравнение не всегда корректно => целесообразно, например делать так:
_FR>
_FR>var d1 = 11 / 3.3;
_FR>var d2 = 33 / 9.9;
_FR>Debug.Assert(Math.Abs(d1-d2)<1e-10, "d1 == d2");
_FR>
Re: (double)0.001f = 0.0010000000474974513. Почему???
От: wallaby  
Дата: 19.01.10 02:53
Оценка:
Здравствуйте, barn_czn, Вы писали:

_>Собственно сабж.

_>Народ, может мне ктонить ответить мочему так работает приведение.
_>У меня есть предположение что шум появляется из-за того что размер float меньше размера double, и оставшаяся часть мантисы заполняется шумом.
_>Вопрос — почему шумом а не нулями?

Не шумом, а именно нулями (двоичными). Теперь откуда берутся десятичные цифры в конце double:
Число 0.001 в формате Single записывается как

0x3A83126F = 0011.1010.1000.0011.0001.0010.0110.1111


В этой записи первый бит — знак (+), следующие 8 битов — экспонента со смещением 127, остальные 23 бита — мантисса (без скрытого единичного бита)
Я разделил эти части точками и добавил скрытый бит мантиссы:

  0.01110101.(1)00000110001001001101111


Значение экспоненты 0x75 = 117; Вычитаем смещение 117 — 127 = -10
Таким образом в формате Single имеем

0.001 = (1 + 1/64  + 1/128 + 1/2^11 + 1/2^14 + 1/2^17 + 1/2^18 + 1/2^20 + 1/2^21 + 1/2^22 + 1/2^23)/2^10


Посчитай выражение справа на калькуляторе с двойной точностью (виндовый подойдёт) и напиши что получится.
---
The optimist proclaims that we live in the best of all possible worlds; and the pessimist fears this is true
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.