Re[3]: Java пытается маскировать неточную природу double-ов
От: CreatorCray  
Дата: 21.02.22 21:05
Оценка:
Здравствуйте, vsb, Вы писали:

vsb>Ну я примерно так и считал. 1/4 * (1 + 3/16 + 3/(16^2) + ... + 3/(16^13)).

Суров и беспощаден!
... << RSDN@Home 1.3.110 alpha 5 rev. 62>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: Java пытается маскировать неточную природу double-ов
От: Shtole  
Дата: 22.02.22 07:44
Оценка:
Здравствуйте, vsb, Вы писали:

>Судя по всему любое число, представимое в десятичной нотации вроде 0.000123 они при toString в первую очередь переводят в подобную нотацию и потом округляют уже это десятичное число.


Как они это определяют?
Do you want to develop an app?
Re[2]: Java пытается маскировать неточную природу double-ов
От: vsb Казахстан  
Дата: 22.02.22 11:28
Оценка: 3 (1)
Здравствуйте, Shtole, Вы писали:

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


>>Судя по всему любое число, представимое в десятичной нотации вроде 0.000123 они при toString в первую очередь переводят в подобную нотацию и потом округляют уже это десятичное число.


S>Как они это определяют?


Основной алгоритм тут там функция на 350 строк, мне это было не настолько интересно, чтобы пытаться её осилить. Но комментариев там много, при желании, думаю, разобраться можно.
Отредактировано 22.02.2022 11:30 vsb . Предыдущая версия . Еще …
Отредактировано 22.02.2022 11:29 vsb . Предыдущая версия .
Re[2]: Java пытается маскировать неточную природу double-ов
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 22.02.22 12:45
Оценка:
Здравствуйте, halo, Вы писали:

H>Я в этом аспекте совершенно не силён, но java.lang.Object.toString() тут ни при чём, как и форматирование. 0.3d — константа с точки зрения языка, и именно в таком виде javac отдаёт значение в пул констант в класс-файла: 0x3FD3333333333333. Почему это считается 0.3d, а не 0.299999999999999988897769753748434595763683319091796875000000 -- не знаю.


На этом уровне действительно имеет смысл говорить о самом коротком представлении, равном данному.

H> И, навскидку, так же ведут себя JavaScript (V8), Python 2.7 в своих REPL-ах, в то время как, например, вывод System.Console.WriteLine() в C# округляет сумму в любом случае (даже если "замаскировать" исходные значения за методами, или использовать System.String.Format("{0:F...}") и System.BitConverter.Int64BitsToDouble; "читерит" даже больше чем Java). Т.е., должно быть стандартное правило, допускающее такое поведение.


Кто читерит в C#, я не понял. Вот у меня дотнет 7.0.100-preview.1.22110.4 (из снапа убунты).

  Скрытый текст
double a = 0.3;
Console.WriteLine("{0:F14}", a);
Console.WriteLine("{0:F15}", a);
Console.WriteLine("{0:F16}", a);
Console.WriteLine("{0:F17}", a);
Console.WriteLine("{0:F18}", a);
Console.WriteLine("{0:F19}", a);
Console.WriteLine("{0:F54}", a);
double b = 0.1;
b *= 3;
Console.WriteLine("{0:F14}", b);
Console.WriteLine("{0:F15}", b);
Console.WriteLine("{0:F16}", b);
Console.WriteLine("{0:F17}", b);
Console.WriteLine("{0:F18}", b);
Console.WriteLine("{0:F19}", b);
Console.WriteLine("{0:F54}", b);


Запускаю:

0.30000000000000
0.300000000000000
0.3000000000000000
0.29999999999999999
0.299999999999999989
0.2999999999999999889
0.299999999999999988897769753748434595763683319091796875
0.30000000000000
0.300000000000000
0.3000000000000000
0.30000000000000004
0.300000000000000044
0.3000000000000000444
0.300000000000000044408920985006261616945266723632812500


По-моему, всё честно без обсуждаемых шуток Java.

У него есть режим вывода "самое короткое представление"? Я быстрым гуглением не нашёл.
The God is real, unless declared integer.
Re[3]: Java пытается маскировать неточную природу double-ов
От: halo Украина  
Дата: 22.02.22 14:05
Оценка:
Здравствуйте, netch80, Вы писали:

N>Кто читерит в C#, я не понял. Вот у меня дотнет 7.0.100-preview.1.22110.4 (из снапа убунты).

Недосмотрел, понадеявшись на единое поведение от версии к версии.
$ mcs --version
Mono C# compiler version 4.6.2.0


Хорошо, допустим, виноват древний Mono. В то же время, быстрая проверка на dotnetfiddle.net при выполнении
private static double a() { return 0.1; }
private static double b() { return 0.2; }
    
public static void Main() {
    Console.WriteLine("{0:F54}", a() + b()); // не заинлайнит (?)
}


показывает следующие результаты:
* .NET 4.7.2: 0.300000000000000000000000000000000000000000000000000000 (аналогично моему примеру вчера)
* .NET 6: 0.300000000000000044408920985006261616945266723632812500

Ваш пример в варианте с .NET 4.7.2 кроме вариций 0.3(0) ничего не показывает. В то же время, Console.WriteLine("{0:X}", BitConverter.DoubleToInt64Bits(0.3)); и Console.WriteLine("{0:X}", BitConverter.DoubleToInt64Bits(0.1 + 0.2)); ведут себя одинаково от версии к версии, и совершенно так же, как в Java для аналогичного кода (0x3FD3333333333333 и 0x3FD3333333333334 соответственно).

N>У него есть режим вывода "самое короткое представление"? Я быстрым гуглением не нашёл.

Понятия не имею. Я пытался найти такое только для JLS, как следствие работы javac, а не как следствие работы Object.toString() как заявлялось в начале темы. Как оно же действительно работает, меня не сильно волнует.
Отредактировано 22.02.2022 14:26 halo . Предыдущая версия . Еще …
Отредактировано 22.02.2022 14:22 halo (-mcs --help / +mcs --version) . Предыдущая версия .
Re[3]: Java пытается маскировать неточную природу double-ов
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 22.02.22 14:30
Оценка:
Здравствуйте, netch80, Вы писали:

S>>В современных языках parseInt(Number("0.0000005")) выдаёт 5


N>Достаточно просто parseInt(0.00000005)


The parseInt() function parses a string argument...

Re[4]: Java пытается маскировать неточную природу double-ов
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 22.02.22 14:48
Оценка:
Здравствуйте, Ikemefula, Вы писали:

S>>>В современных языках parseInt(Number("0.0000005")) выдаёт 5


N>>Достаточно просто parseInt(0.00000005)


I>

I>The parseInt() function parses a string argument...


И?

$ node
> parseInt(0.000005)
0
> parseInt(0.0000005)
5


Выдаёт результат? исключения нет? Всё, закомпостировано.
The God is real, unless declared integer.
Re[5]: Java пытается маскировать неточную природу double-ов
От: vaa  
Дата: 24.02.22 06:05
Оценка:
Здравствуйте, netch80, Вы писали:

N>Ааа, cl это Common LISP... там, да, свой мир, весьма интересный.


Вспомнил, тоже с флоатом заметил проблему когда играл с sbcl-x64!

(log 24000.0 2.0)
;; 14.550746
(setf *read-default-float-format* 'double-float) ;; <= подсказали в телеге
;; DOUBLE-FLOAT
(log 24000.0 2.0)
;; 14.550746785383243
☭ ✊ В мире нет ничего, кроме движущейся материи.
Re[5]: Java пытается маскировать неточную природу double-ов
От: vsb Казахстан  
Дата: 24.02.22 06:28
Оценка:
Здравствуйте, netch80, Вы писали:

N>
N>$ node
>> parseInt(0.000005)
N>0
>> parseInt(0.0000005)
N>5
N>


N>Выдаёт результат? исключения нет? Всё, закомпостировано.


Наверное ты и так знаешь, но поясню на всякий случай. parseInt конвертирует аргумент в строку. (0.000005).toString() === '0.000005', а (0.000005).toString() === '5e-7'. parseInt парсит строку до первого неправильного (в плане представления целых чисел) символа и возвращает всё, что смог напарсить. В первом случае он парсит 0, натыкается на точку и возвращает 0. Во втором случае он парсит 5, натыкается на e и возвращает 5. Если заменить parseInt на parseFloat то всё будет работать.

Из того же разряда
parseInt(100000000000000000000)
100000000000000000000
parseInt(1000000000000000000000)
1
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.