powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Java [игнор отключен] [закрыт для гостей] / Тип Double - 1.1*1.1 = 1.2100000000000002
25 сообщений из 30, страница 1 из 2
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39294996
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Доброго дня господа
Работаю с финансовой задачей, имею проблему с типом Double

1.1*1.1 = 1.2100000000000002 ????????

Суть проблемы в целом ясна, не ясно как попроще решить
Прошу Вашего совета

Например так, но BigDecimal не дает нужной точности

Код: java
1.
2.
    java.math.BigDecimal b = new java.math.BigDecimal(1.1*1.1); 
    System.out.println(b);   //1.2100000000000001865174681370262987911701202392578125



Код: java
1.
2.
3.
4.
5.
6.
	private static Double round(Double value,int count)
	{
		Double decim=Math.pow(10.0,count);
		return (double) Math.round(Math.abs(value)*decim)/decim*Math.signum(value);
        //return new BigDecimal(value).setScale(count*2,RoundingMode.HALF_UP).setScale(count*1,RoundingMode.HALF_UP).doubleValue();
	}



Заранее благодарен
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295000
just_vladimir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Не очень понял, что Вам нужно, но может быть поможет:
Код: java
1.
2.
3.
4.
5.
MathContext mt = new MathContext(5, RoundingMode.HALF_UP);
BigDecimal a = new BigDecimal(1.1, mt);
BigDecimal b = new BigDecimal(1.1, mt);
BigDecimal c = a.multiply(b);
System.out.println(c);
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295006
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
дабл и финансы - несовместимые вещи. и где это там у вас что за такая фин.задача, если точности бигдеца не хватает???
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295009
Фотография Usman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X
Код: java
1.
java.math.BigDecimal b = new java.math.BigDecimal(1.1*1.1); 

Очевидно, что проблемы "double" перенеслись в BigDecimal.

А если сделать так:
Код: java
1.
2.
java.math.BigDecimal bd1_1 = java.math.BigDecimal.ONE.add(java.math.BigDecimal.ONE.divide(java.math.BigDecimal.TEN)); // 1 + 1/10
System.out.println(bd1_1.multiply(bd1_1)); // 1.1 * 1.1 = 1.21

то все ок
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295037
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
лол. еще проще. вообще так нельзя создавать бигдецы из дабла. а в первом сообщении вообще в бигдец вталкивается уже кривое значение выражения.

туда надо вкидывать или стринг (создавая значение). или так:

автор BigDecimal a = BigDecimal.valueOf(1.1);
BigDecimal b = BigDecimal.valueOf(1.1);
System.out.println(a.multiply(b).toString());


но тут вот тоже кстати, некоторые почему-то не рекомендуют ТАК создавать бигдецы. хотя.. я создавал и софт писал и расхождений с той же 1с-кой в результатах не наблюдалось.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295050
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Тема - старый боян. Дробная часть - в double/float не кодируется а апроксимируется.

Тоесть ее величина - приближенная. Есть частные случаи когда она точно равна.
Это дроби вида 1/2,1/4, 1/8 и производные суммы от них. Количество членов этого
ряда ограничено. Для float оно еще меньше. Тоесть можно сказать что floating-point
типы сжимают любое вещественное число в некий enumeration из известного набора
констант.

А все прочие вещественные числа будут закодированы с потерями. Как вы будете
отрабатывать эти потери - это дело ваше. Это дело прикладное. И оно не касается
самого типа double. Он уже свою задачу выполнил. Это ваша личная ответственность
как знатока арифметики и десятичной бухгалтерской системы.

А лучше действительно кодируйте в BigDecimal.

Если сильно интересно что это за магия констант - курите

Код: java
1.
2.
Math.nextUp(double)
Math.nextDown(double)

(Это что-то вроде итератора по оси вещественных чисел.)

Код: java
1.
2.
Double.longBitsToDouble(long)
Double.doubleToRawLongBits(double)


Это служебные native функции которые позволяют получить сырое представление
double в памяти.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295085
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

Да это по сути ничего не меняет (применение другого типа), суть в том что я не знаю когда именно
идет искажение в ЛЮБОМ типе, а когда это корректная величина.
Т.е. насколько и как округлять


Пример
8297.69/12 = 691.474166666667 - ИСТИНА
936.3/12 = 78.025 - ИСТИНА

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
	public static void main(String[] args) 
	{
		round(8297.69/12.0,2);
		round( 936.30/12,2);
		java.math.BigDecimal b = new java.math.BigDecimal(8297.69/12.0); 
		System.out.println(b);
		java.math.BigDecimal r = new java.math.BigDecimal( 936.30/12.0); 
		System.out.println(r);
	}

	private static Double round(Double value,int count)
	{
		Double scale=Math.pow(10.0,count);
		System.out.println(value);
		System.out.println(Math.signum(value)*Math.round((Math.round(Math.abs(value)*scale*1.0)/1.0))/scale);     
		System.out.println(Math.signum(value)*Math.round((Math.round(Math.abs(value)*scale*10.0)/10.0))/scale);  
		return (double) Math.signum(value)*Math.round((Math.round(Math.abs(value)*scale*1.0)/1.0))/scale;
		//return (double) Math.signum(value)*Math.round((Math.round(Math.abs(value)*scale*10.0)/10.0))/scale;
	}



Результат
691.4741666666667 - дробная часть корректна
691.47
691.47
78.024 99999999999 - эти девятки лишние число делиться нацело
78.02
78.03

BigDecimal
691.4741666666667470053653232753276824951171875
78.0249999999999914734871708787977695465087890625 - опять лишние девятки

А если округлять сначала до третьего, потом до второго - все равно имеем ошибку, но другого типа.

Что скажите ?


Спасибо за уделенное время
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295122
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,

ты маешься фигней. забудь о даблах. ты утархаешься с ними когда у тебя пойдут более-менее каскадные вычисления какой-нибудь финансовой фигни.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295123
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
я тоже в свое время пытался с этими раундами изобрести сильвербулет для дабла. не вышло. )))
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295142
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
natanabrahamjrHOME_X,

ты маешься фигней. забудь о даблах. ты утархаешься с ними когда у тебя пойдут более-менее каскадные вычисления какой-нибудь финансовой фигни.


У меня ИДУТ каскадные вычисления финансовой фигни.....
отсюда и спрашиваю, чем можно адекватно заменить ?
(BigDecimal - аналогичен)
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295153
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_XПример
8297.69/12 = 691.474166666667 - ИСТИНА
936.3/12 = 78.025 - ИСТИНА


Что означает этот модульный тест?

Почему вы пишете о какой-то истине. Вот в Lisp результат другой.

Код: java
1.
2.
3.
4.
[1]> (/ 8297.69 12)
691.4742
[2]> (/ 936.30 12)
78.025
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295157
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_XА если округлять сначала до третьего, потом до второго - все равно имеем ошибку, но другого типа.

Что скажите ?

Скажу что это неверная постановка задачи. Само по себе понятие округления безсмысленно
по отношению к double? Double принципиально не округляется. Округляется его строковое десятичное
представление. А если вы оперируете с этим предсавлением ( BCD, BigDecimal, symbolic, money ) арифметикой то зачем вам double?
Вы уже задействовали механизмы на порядки более тяжелые чем double. Улавливаете?

Если вам так лень использовать синтаксис java в отношении BigDecimal - посмотрите в сторону Scala или Groovy.
Возможно там синтаксис более удобен для бухгалтерии.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295183
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЧто означает этот модульный тест?


Это просто пример - не обращайте внимания...
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295186
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
maytonЕсли вам так лень использовать синтаксис java в отношении BigDecimal - посмотрите в сторону Scala или Groovy.


Мне необходимо просчитать порядка 50-70 полей объекта
Тип расчета - финасово-бухгалтерский.
Операции - математика средней школы (+ - / * )
Размерность полей 18.2, 18.8

Тип Double взят как базовый, предполагал что он максимально
прост без конструкторов и прочих излишеств
BigDecimal - дает те же погрешности Вы это видели из примеров.

Scala или Groovy - зачем так сложно ?

В Java нет простого математического типа ?
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295190
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хоум, ты понимаешь, что когда ты делаешь ТАК:

ava.math.BigDecimal r = new java.math.BigDecimal( 936.30/12.0);

это НЕ БИГ ДЕЦИМАЛ. ты в дабле делаешь это уродское число а потом передаешь его как есть в бигдец. а потом говоришь бигдец не работает.. )) прочитай ты мануал наконец. или стаковерфлоу.

вот тебе твой код и мой код сравни оба значения и удивись:

Код: java
1.
2.
3.
4.
        BigDecimal a = BigDecimal.valueOf(936.30);
        BigDecimal b = BigDecimal.valueOf(12.0);
        System.out.println(a.divide (b).toString());
        System.out.println(new java.math.BigDecimal( 936.30/12.0));



если ты тут не видишь разницы - то прочти наконец хотяб книжку ява-хеад-ферст.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295194
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
natanabrahamjr,

Понял Вас - спасибо
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295198
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,

я прошу прощения если был сугубо резок. но на самом деле, вы наступаете на грабли, на которые уже много раз до вас наступали. посему не изобретайте велосипед. бигдец - это хрошая вещь, там и округление можете подключать и обрезку и т.п. при правильно использвании с той же адинэской расхождений не будет. а проблема округления это в принципе, такая вещь, с которой все бухи сталкиваются. делайте просто как они хотят и всё.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295206
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_XВ Java нет простого математического типа ?
Да. В Java действительно нет простого математического (примитивного типа).
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295208
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton,

....а еще в ней нет переопределения операторов... хотя... в джейэспи ты без проблем можешь писать бигдец1+бигдец2 - бигдец3. и оно даже работать будет нормально.
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295213
Фотография mayton
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
нет
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295218
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
что нет?

будет. и работает. и будет и работает. :)
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295219
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mayton, natanabrahamjr

Очень благодарен за ответы господа !

P.S.
maytonДа. В Java действительно нет простого математического (примитивного типа).


Блин - траханина на пустом месте.....
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39295224
natanabrahamjr
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HOME_X,
на первый взгляд да. а на второй и третий - со временем привыкните преобразовывать математические действия в последовательность вида: a.multiply(b).divide(c).add(d.substract(e)).setScale(2,BigDecimal.ROUND_HALF_UP).toString();
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39304680
Leonid Kudryavtsev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Мне кажется, в ситуациях 1.1 * 1.1 проблема в постановке задачи

1) BigDecimal нужен, когда мы оперируем деньгами - складываем, вычитаем и так далее

если это 1 рубль 10 коп. x 1.1 кило картошки = то ответ 1 рубль 21 коп. и потери точности при BigDecimal взяться не откуда. 2 знака после запятой и не е.... IMHO

2) если проблема, что данные глобально отличаются от данных суммированных по строкам:

купили 100 кг. картошки по 1.10, а продаем в пачках по 10 грамм по себестоимости ( 1р10к/0.01=0,011=1 коп и 0.1 коп потерялась)

То эта проблема давно решена в бухгалтерии, есть отдельные счета для расхождений, куда это расхождение и должно быть записано. IMHO & AFAIK
...
Рейтинг: 0 / 0
Тип Double - 1.1*1.1 = 1.2100000000000002
    #39304694
HOME_X
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Leonid Kudryavtsev1) BigDecimal нужен, когда мы оперируем деньгами - складываем, вычитаем и так далее


Оперируем деньгами,
BigDecimal мне не нравиться - сложен в использовани

a.multiply(b).divide(c).add(d.substract(e)).setScale(2,BigDecimal.ROUND_HALF_UP).toString()
слишком непонятно и нечитабельно
...
Рейтинг: 0 / 0
25 сообщений из 30, страница 1 из 2
Форумы / Java [игнор отключен] [закрыт для гостей] / Тип Double - 1.1*1.1 = 1.2100000000000002
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]