Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > JavaScript: Общие вопросы > Арифметика в JS


Автор: Bastet 10.10.2005, 22:50
Не знаю, у всех ли такие глюки, но на одном моем друге проверено.
Просто методом алерт получаю:
Код

alert (3*0.7);

Цитата
3*0.7 = 2.0999999..., однако
0.3*0.7 = 0.21


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

Автор: sergejzr 10.10.2005, 23:06
К сожалению нельзя конечным количеством бит представить любое число.
Числа с пл. точкой на самом деле съэмитированы.
Поэтому подобные неточности вообще не зависят от языка программирования, а являются особенностью нашего железного цифрового друга.

Обойти.... ну разве что написать свой класс чисел. И выполнять арифметические операции столбиком. Но вот беда мы и там не застрахованы. Хотя...

Код

function myMult(a,b)
{
  res=parseInt((a*100)+"")*parseInt((b*100)+"");
  return res/100;
}


Только операции с целыми числами дают точные результаты (пока мы не вышли за границы определённые количеством бит, используемых для хранения этого числа..)
Добавлено @ 23:08
Ссори за тупизну с parseInt просто на скорую руку не вспомню, как в целое число преобразовать плавающее ...

Автор: Aliance 10.10.2005, 23:15
Цитата(sergej @ 11.10.2005, 00:06)
Ссори за тупизну с parseInt просто на скорую руку не вспомню, как в целое число преобразовать плавающее ...

parseFloat?

Автор: sergejzr 10.10.2005, 23:18
неа parseFloat это строку в дес. дробь.
А надо дес. дробь в целое число (просто обрезать нули).

В С++ и Java:
double a=5.6;
int g=(int)a;

Автор: Aliance 10.10.2005, 23:59
>>>как в целое число преобразовать плавающее
>>>А надо дес. дробь в целое число

Противоречишь сам себе 8))

Автор: Sardar 11.10.2005, 00:10
Одно из фундаментальных свойств дробных чисел: между двумя различными числами всегда существует третье, отличное от первых двух. Реализовать это не реально по определению, память конечна)

В JS, как в прочем почти везде, дробные числа представляються 64 битным числом, состоящим из знакового бита, мантиссы и экспоненты. Об этом много раз говорилось на форуме и даже в JS smile

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

parseInt и parseFloat использовать не нужно, юзаем toFixed(<число знаков после запятой>);

Код
alert(0.7989889990.toFixed(2));

Автор: Bastet 11.10.2005, 00:16
Как преобразовать одно число в другое найду по справочнику...

Ясно одно: красивого пути решения проблемы нет.
sergej.z, наверное, так и придется.

Нужно для интереса попробовать в других языках умножать 3 на 0.7 smile

Автор: sergejzr 11.10.2005, 00:25
Цитата(Bastet @ 10.10.2005, 23:16)
Нужно для интереса попробовать в других языках умножать 3 на 0.7 smile

можно и не пробовать smile поюзай поиск по форуму. В каждом разделе Х бывал такой вопрос, почему язык Х врёт smile smile

Вот, точностью можешь вариировать. Параметр к toFixed - число занаков после запятой в наиболее "длинном" числе. Делить в конце ессно надо на 10 в степени это количество. Думаю разберёшься и так smile

Код

function myMult(a,b)
{
  res=a.toFixed(4)*b.toFixed(4)
  return res/10000;
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)