Return Value
value rounded to the nearest 16-bit signed integer. If value is halfway between two whole numbers, the even number is returned; that is, 4.5 is converted to 4, and 5.5 is converted to 6.
В то время как явное приведение типов через (int) возвращает ближайшее целое, меньшее, чем результат. А что касается внутреннего представления float, то никто не гарантирует, что 0.9f в памяти не хранится как 0.899999. Отсюда и проблемы с преобразованием.
"Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете". (с) Макконнелл, "Совершенный код".
Re[2]: Округление? Почему так?
От:
Аноним
Дата:
03.07.08 06:11
Оценка:
Где логика?)
int f1 = (int)(10* 0.9f); // 8
int f2 = (int)(10* 0.8f); // 8
int f3 = (int)(10* 0.7f); // 6
int f4 = (int)(10* 0.6f); // 6
int f5 = (int)(10* 0.5f); // 5
int f6 = (int)(10* 0.4f); // 4
int f7 = (int)(10* 0.3f); // 3
int f8 = (int)(10* 0.2f); // 2
Если заглянуть вглубь, то как представлена константа в формате IEEE c плавающей точкой?
Когда мы пишем 0.9 = то мантисса = 899999976158142 и запятая помещается после первого разряда?
Тогда почему бы мантиссу не представить как 9? Ведь все можно проще сделать? Откуда погрешность возникает?
Z>>Тогда почему бы мантиссу не представить как 9? Ведь все можно проще сделать? Откуда погрешность возникает?
Мантисса не может быть "представлена как 9", т.к. она хранится в нормализованном виде, т.е. для чисел с плавающей запятой (в десятичном представлении): 0.5 <= Мантисса < 1.0. И вот из-за неточного представления десятичных дробей в двоичном коде и появляется погрешность.
Здравствуйте, Овощ, Вы писали:
Z>>>Тогда почему бы мантиссу не представить как 9? Ведь все можно проще сделать? Откуда погрешность возникает?
О>Мантисса не может быть "представлена как 9", т.к. она хранится в нормализованном виде, т.е. для чисел с плавающей запятой (в десятичном представлении): 0.5 <= Мантисса < 1.0. И вот из-за неточного представления десятичных дробей в двоичном коде и появляется погрешность.
Все равно не понял.
0.9 представим как a*(q^n)
а = мантисса = 9
q = система счисления = множитель = 10
n = показатель степени = -1
Итого: 0,9=9*10^-1
Откуда погрешность?
Если у нас число с плавающей запятой, то
— мантиссу 9 представим в двоичном виде как 1001
— множитель 10 = 1010
— степень -1 = 1111...11 (кол-во 1-ц в зависимости от разрядности)
Все это можно упаковать в 32 битное число с плавающей запятой без погрешности.
Здравствуйте, zbanned, Вы писали:
Z>Здравствуйте, Овощ, Вы писали:
Z>>>>Тогда почему бы мантиссу не представить как 9? Ведь все можно проще сделать? Откуда погрешность возникает?
О>>Мантисса не может быть "представлена как 9", т.к. она хранится в нормализованном виде, т.е. для чисел с плавающей запятой (в десятичном представлении): 0.5 <= Мантисса < 1.0. И вот из-за неточного представления десятичных дробей в двоичном коде и появляется погрешность.
Z>Все равно не понял. Z>0.9 представим как a*(q^n) Z>а = мантисса = 9 Z>q = система счисления = множитель = 10 Z>n = показатель степени = -1 Z>Итого: 0,9=9*10^-1 Z>Откуда погрешность? Z>Если у нас число с плавающей запятой, то Z>- мантиссу 9 представим в двоичном виде как 1001 Z>- множитель 10 = 1010 Z>- степень -1 = 1111...11 (кол-во 1-ц в зависимости от разрядности) Z>Все это можно упаковать в 32 битное число с плавающей запятой без погрешности.
Z>Поясните, где не прав?
А ты распиши также число 9,346242 и поймешь в чем неправ.
Здравствуйте, zbanned, Вы писали:
Z>Ок. Давай пока по проще. Хорошо, возмем q=2. Тогда получается большая погрешность: Z>0,9 ~= 9*2^-3 = 9/8 = 1,125 Z>или Z>0,9 ~= 9*2^-4 = 9/16 = 0,5625
Z>Откуда тогда берется 0,8999999?
Как уже было замечено эта погрешность происходит из-за преобразования чисел. Она заключается в том, что число 0.9 в компьютере хранится в двоичном виде, а не в десятичном, а вводишь ты его в десятичном. Попробуй преобразовать число 0.9 в двоичный вид, затем преобразовать обратно в десятичный, и ты увидишь, что это итоговое число будет близко к 0.9, но оно не будет ему равно, и величина этой погрешности зависит от количества знаков, которое занимает мантисса: чем больше разрядность мантиссы, тем меньше погрешность.
Здравствуйте, Niswn, Вы писали:
N>Здравствуйте, zbanned, Вы писали:
Z>>Ок. Давай пока по проще. Хорошо, возмем q=2. Тогда получается большая погрешность: Z>>0,9 ~= 9*2^-3 = 9/8 = 1,125 Z>>или Z>>0,9 ~= 9*2^-4 = 9/16 = 0,5625
Z>>Откуда тогда берется 0,8999999?
N>Как уже было замечено эта погрешность происходит из-за преобразования чисел. Она заключается в том, что число 0.9 в компьютере хранится в двоичном виде, а не в десятичном, а вводишь ты его в десятичном. Попробуй преобразовать число 0.9 в двоичный вид, затем преобразовать обратно в десятичный, и ты увидишь, что это итоговое число будет близко к 0.9, но оно не будет ему равно, и величина этой погрешности зависит от количества знаков, которое занимает мантисса: чем больше разрядность мантиссы, тем меньше погрешность.
Как уже сказали на 4 сообщения выше — ошибка из-за преобразования и я это сразу же понял после первого поста.
Я уже два раза преобразовал и в двоичном виде, и в десятичном, все равно не нашел момента где у нас теряется эта маленькая величина. Если мы разложим 0,9 как aq^n при q = 2 то у нас может быть только два варианта:
0,9 ~= 9*2^-3 = 9/8 = 1,125
или
0,9 ~= 9*2^-4 = 9/16 = 0,5625
Ни один из них не дает нам ни первоначальный 0.9, ни сишный 0,8999999.
Помогите правильно преобразовать 0,9 в формат с плавающей запятой, я был бы очень рад.
Здравствуйте, zbanned, Вы писали:
Z>Как уже сказали на 4 сообщения выше — ошибка из-за преобразования и я это сразу же понял после первого поста. Z>Я уже два раза преобразовал и в двоичном виде, и в десятичном, все равно не нашел момента где у нас теряется эта маленькая величина. Если мы разложим 0,9 как aq^n при q = 2 то у нас может быть только два варианта: Z>0,9 ~= 9*2^-3 = 9/8 = 1,125 Z>или Z>0,9 ~= 9*2^-4 = 9/16 = 0,5625 Z>Ни один из них не дает нам ни первоначальный 0.9, ни сишный 0,8999999.
Какую-то ересь написал.
Z>Помогите правильно преобразовать 0,9 в формат с плавающей запятой, я был бы очень рад.
Мантисса вещественных чисел хранятся как разложение по 2^(-n).
0.9 — 2^(-1) = 0.9-0.5 = 0.4 в результат уходит 1
0.4 — 2^(-2) = 0.4 — 0.25 = 0.15 в результат уходит 1
0.15 — 2^(-3) = 0.15 — 0.125 = 0.025 в результат уходит 1
0.025 < 2^(-4) в результат уходит 0
0.025 < 2^(-5) в результат уходит 0
0.025 — 2^(-6) = 0.025 — 0.015625 = 0.009375 в результат уходит 1
...
Так можно продолжать долго, результат не станет нулевым. Тем не менее бит на мантиссу у нас ограниченное количество, поэтому возникают ошибки представления чисел с плавающей точкой и 0.9 на самом деле равно 0.89999999
Здравствуйте, zbanned, Вы писали: Z>Как уже сказали на 4 сообщения выше — ошибка из-за преобразования и я это сразу же понял после первого поста. Z>Я уже два раза преобразовал и в двоичном виде, и в десятичном, все равно не нашел момента где у нас теряется эта маленькая величина. Если мы разложим 0,9 как aq^n при q = 2 то у нас может быть только два варианта: Z>0,9 ~= 9*2^-3 = 9/8 = 1,125 Z>или Z>0,9 ~= 9*2^-4 = 9/16 = 0,5625 Z>Ни один из них не дает нам ни первоначальный 0.9, ни сишный 0,8999999.
Z>Помогите правильно преобразовать 0,9 в формат с плавающей запятой, я был бы очень рад.
Хорошо. Поясню на примере. gandjustas уже написал один пример, но нас учили немного по другому переводить число в двоичное, поэтому это может будет кому интересно (хотя нас этому учили на информатике в школе).
число 9 = 1001 (это надеюсь понятно)
число 0.9 НЕ РАВНО 0.1001
Нас учили так преобразовывать дроби:
1. берем число от 0 до 1.
2. умножаем его на два.
3. если число больше еденицы, то вычитаем еденицу (в результате опять получится число 0..1). И записываем 1 как i-тую цифру после запятой двоичного числа.
4. если число после умножение меньше еденицы, то ничего не делаем. И записываем 0 как i-тую цифру после запятой двоичного числа.
5. повторяем шаги 2-4 пока в результате не получится ноль.
получаем двоичное число 0.111001.....
Это можно продолжаться до бесконечности, а мантисса у нас ограничена. отсюда и появляется погрешность. чем больше двоичное число будет содержать разрядов после запятой (а это определяется разрядностью мантиссы), тем меньше будет погрешность.
К примеру, число 0.75 сводится в ноль за 2 шага и в двоичном виде будет выглядеть как 0.11. Поэтому оно не будет иметь погрешность при преобразовании.
Народ, спасибо всем огромное за ответы! Все дошло до меня
Один вопрос остался: почему пошли именно таким путем деления? Почему бы не представить мантиссу 9 просто как 1001 (без деления)?
Т.е. можно же 32 битное число для плавающей запятой, просто разделить на две части на 16 и 16 бит и упаковать туда мантиссу со степенью, например так:
16 бит под мантиссу (знаковое 16-битное целое);
16 бит под степень (тоже знаковое 16-битное целое);
В итоге можно 0.9 представилось бы как
0000 0000 0000 1001 под мантиссу и
1111 1111 1111 1111 под степень в двоичном виде.
А число 9 представилось бы как:
0000 0000 0000 1001 под мантиссу и
0000 0000 0000 0000 под степень в двоичном виде.
И все считать по основанию 10ой системы. Для чего понадобилось таким хитрым способом переводить мантиссу делением?
Здравствуйте, zbanned, Вы писали:
Z>Один вопрос остался: почему пошли именно таким путем деления? Почему бы не представить мантиссу 9 просто как 1001 (без деления)?
Аппаратная арифметика при чисто двоичном представлении проще. В 85 году, когда был выпущен IEEE 754, это было крайне важно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1095 on Windows Vista 6.0.6001.65536>>
Здравствуйте, zbanned, Вы писали:
Z>Один вопрос остался: почему пошли именно таким путем деления? Почему бы не представить мантиссу 9 просто как 1001 (без деления)? Z>Т.е. можно же 32 битное число для плавающей запятой, просто разделить на две части на 16 и 16 бит и упаковать туда мантиссу со степенью, например так: Z>16 бит под мантиссу (знаковое 16-битное целое); Z>16 бит под степень (тоже знаковое 16-битное целое);
Z>В итоге можно 0.9 представилось бы как Z>0000 0000 0000 1001 под мантиссу и Z>1111 1111 1111 1111 под степень в двоичном виде.
Z>А число 9 представилось бы как: Z>0000 0000 0000 1001 под мантиссу и Z>0000 0000 0000 0000 под степень в двоичном виде.
И получили бы точность в 5 десятичных знаков. Сейчас бы еще больше плевались при таком раскладе.
Более того, такое кодирование избычно. Позволяет записать одно и тоже число несколькими способами, следовательно диапазон значений меньше.
Z>И все считать по основанию 10ой системы. Для чего понадобилось таким хитрым способом переводить мантиссу делением?
1)Однозначность хранимого числа
2)Оптимальность хранения
3)Быстродействие арифметических операций
Здравствуйте, zbanned, Вы писали:
Z>Один вопрос остался: почему пошли именно таким путем деления? Почему бы не представить мантиссу 9 просто как 1001 (без деления)? Z>Т.е. можно же 32 битное число для плавающей запятой, просто разделить на две части на 16 и 16 бит и упаковать туда мантиссу со степенью, например так: Z>16 бит под мантиссу (знаковое 16-битное целое); Z>16 бит под степень (тоже знаковое 16-битное целое);
Z>В итоге можно 0.9 представилось бы как Z>0000 0000 0000 1001 под мантиссу и Z>1111 1111 1111 1111 под степень в двоичном виде.
Z>А число 9 представилось бы как: Z>0000 0000 0000 1001 под мантиссу и Z>0000 0000 0000 0000 под степень в двоичном виде.
Z>И все считать по основанию 10ой системы. Для чего понадобилось таким хитрым способом переводить мантиссу делением?
A decimal number is a floating-point value that consists of a sign, a numeric value where each digit in the value ranges from 0 to 9, and a scaling factor that indicates the position of a floating decimal point that separates the integral and fractional parts of the numeric value.
The binary representation of a Decimal value consists of a 1-bit sign, a 96-bit integer number, and a scaling factor used to divide the 96-bit integer and specify what portion of it is a decimal fraction. The scaling factor is implicitly the number 10, raised to an exponent ranging from 0 to 28. Therefore, the binary representation of a Decimal value is of the form, ((-2^96 to 2^96) / 10^(0 to 28)), where -2^96-1 is equal to MinValue, and 2^96-1 is equal to MaxValue.