Здравствуйте, vsb, Вы писали:
vsb>Судя по всему любое число, представимое в десятичной нотации вроде 0.000123 они при toString в первую очередь переводят в подобную нотацию и потом округляют уже это десятичное число. На мой взгляд это грязный трюк, который скрывает истинную природу double-ов и провоцирует их использовать там, где их использовать не стоит, т.к. создаёт начальную видимость того, что всё работает правильно.
Я в этом аспекте совершенно не силён, но java.lang.Object.toString() тут ни при чём, как и форматирование. 0.3d — константа с точки зрения языка, и именно в таком виде javac отдаёт значение в пул констант в класс-файла: 0x3FD3333333333333. Почему это считается 0.3d, а не 0.299999999999999988897769753748434595763683319091796875000000 -- не знаю. Причём, сумму 0.1d и 0.2d вычисляет уже как 0.30000000000000004d (это отличие для времени компиляции также предусмотрено в JLS): 0x3FD3333333333334. Поведение, по-моему, не зависит ни от версии Java (8 или 17), ни от присутствия модификатора strictfp. Это видно как и в отладчике при осмотре variadic-аргументов, так и в javap при дизассемблировании class-файла. И, навскидку, так же ведут себя JavaScript (V8), Python 2.7 в своих REPL-ах, в то время как, например, вывод System.Console.WriteLine() в C# округляет сумму в любом случае (даже если "замаскировать" исходные значения за методами, или использовать System.String.Format("{0:F...}") и System.BitConverter.Int64BitsToDouble; "читерит" даже больше чем Java). Т.е., должно быть стандартное правило, допускающее такое поведение.