- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
static double SingleToDouble(Single v)
{
return double.Parse(v.ToString());
}
static void Scan()
{
double q = 0.0;
while (q <= 10.0)
{
Single s = (Single)q;
Double d = SingleToDouble(s);
if (d == q)
MessageBox.Show(q.ToString());
q = q + 0.1;
}
}
народ, кто-нибудь знает чем можно заменить код "return double.Parse(v.ToString());" в SingleToDouble?
"return v;" не подходит - на экран выводятся только 0, 0.5 и 4.5. А нужно чтобы все выводились 0, 0.1, 0.2 ... 0.9.
С чего бы? 0.1 не может быть точно представимо в компьютере, поэтому при конвертации туда-сюда такая фигня получается. Это нормально.
if (d == q)
замени на
if abs(d-q) < eps
или не используйте плавающую точку
TarasB объяснил суть проблемы, так что с этим кодом тоже не заработает.
еще немного подробнее о проблеме:
имеется double: q=1.1;
мы присваиваем: Single s=(Single)q;
а потом обратно в Double: double g=s;
получается, что g=0.10000000149011612, т.е. добавляются левые 0.00000000149011612.
Есть ли более "приличный" способ эти левые числа отбросить, кроме как double.Parse(q.ToString("0.########"))?
Просто запомни: никогда не сравнивай вещественные числа оператором "равно".
В результате каких-то расчетов с плавающей запятой получается результат, который сохраняется в файл в 4-х байтном формате, т.е. Single. Формат файла строго регламентирован.
Потом, когда этот результат загрузится из файла (допустим другой программой) и преобразуется в double для дальнейших расчетов, то добавляются левые числа! Вот я и пытаюсь найти какое-нибудь средство, чтобы от левых чисел избавиться.
d := round(d*1000)*0.001
А если тебе нужно хранить точные значение, то терпи что есть.
Ничего лишнего ниоткуда не берётся! Это вещественные числа! А ну марш читать про них!
Они представлены в памяти так, как представлены. Не трогай их! И лишь при показе пользователю используй формат.
0.10000000149011612 и 0.10000000000000000
одно и то же? Мы же точность увеличили с float до double.
double v1 = 1.1;
double v2 = (Single)v1;
v1 *= 10000000000;
v2 *= 10000000000;
и теперь у нас
v1 = 11000000000.0
v2 = 11000000238.418579
Какой смысл в двойной точности, если на промежуточном этапе данные сохраняются в одинарной? Это говноархитектура! Своим говнокодом ты пытаешься заткнуть дыру говноархитектуры приложения.
Совершенно нормально для вычислительной математики, когда точность вычислений у вас выше, чем точность результата. Для задач оптимизации максимальная точность результата -- это корень от точности вычислений (достаточно очевидно это, если с математическим анализом знакомы).
Кроме того, данные могут сохранятся где-то в определённом формате, независящем от программы, производящей вычисления.
Но "говноархитектура" здесь совершенно не очевидна. (далее С++) Скажем, закладывая float в метод Рунге-Кудта второго порядка и рассчитывая во float ответ будет колебаться (то есть фазовая траектория будет "дышать"). А если внести float, рассчитать в double, и снова конвертировать во float, то ответ не изменится (всегда один и те же числа будут получаться, фазовая траектория во float стабильна, но "дышит" в double). Это как раз связано с тем, что начальные и конечные данные имеют точность ниже того, чем нужно считать.
Насколько я понимаю, в процессорах Intel даже существует дополнительное ещё более длинное число, чем double, которое используется в выражениях содержащих плавающую точку, чтобы получать, до некоторой степени, всегда один и тот же результат выражения в пределах точность double.
long double штоле?
Просто он так назвал, как будто это новая сверхсекретная технология Интела.
http://en.wikipedia.org/wiki/Extended_precision
а сам формат нативный, поэтому и длина неправильная получилась
А с чем это связано? С выравниванием?
facepalm.for
ВЕЩЕСТВЕННЫЕ ЧИСЛА СРАВНИВАТЬ ЧЕРЕЗ ОПЕРАТОР СРАВНЕНИЯ НЕЛЬЗЯ!!!
ВЕЩЕСТВЕННЫЕ ЧИСЛА СРАВНИВАТЬ ЧЕРЕЗ ОПЕРАТОР СРАВНЕНИЯ НЕЛЬЗЯ!!!
ВЕЩЕСТВЕННЫЕ ЧИСЛА СРАВНИВАТЬ ЧЕРЕЗ ОПЕРАТОР СРАВНЕНИЯ НЕЛЬЗЯ!!!
ВЕЩЕСТВЕННЫЕ ЧИСЛА СРАВНИВАТЬ ЧЕРЕЗ ОПЕРАТОР СРАВНЕНИЯ НЕЛЬЗЯ!!!
Какого хрена у меня погрешность возникает, когда я в более точное представление конвертирую?
То есть Single сам по себе хранит мало знаков после запятой, но для него погрешность 1Е-7 нормальна. То есть число типа 1.111111111 при выводе заменяется на 10.0
А вот те же 1Е-7 для Double уже не погрешность представления, и 1.111111111000000 выводится как есть.
// то есть через Math.Round(), опечатка.
Если неймётся, то используй round(x*100000)*0.00001
но лучше так не делай.
Лучше почитай книжки или википедию http://ru.wikipedia.org/wiki/Числа_с_плавающей_запятой
PS: за обращение "народ" не стоя на броневичке хочется отдельно уебать
просто съебись отсюда, пожалуйста.
:-P
Ладно, извини, че то я сорвался, день видно сегодня такой.