Здравствуйте, vsb, Вы писали:
>Судя по всему любое число, представимое в десятичной нотации вроде 0.000123 они при toString в первую очередь переводят в подобную нотацию и потом округляют уже это десятичное число.
Как они это определяют?
Do you want to develop an app?
Re[2]: Java пытается маскировать неточную природу double-ов
Здравствуйте, Shtole, Вы писали:
S>Здравствуйте, vsb, Вы писали:
>>Судя по всему любое число, представимое в десятичной нотации вроде 0.000123 они при toString в первую очередь переводят в подобную нотацию и потом округляют уже это десятичное число.
S>Как они это определяют?
Основной алгоритм тут там функция на 350 строк, мне это было не настолько интересно, чтобы пытаться её осилить. Но комментариев там много, при желании, думаю, разобраться можно.
Здравствуйте, 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 (из снапа убунты).
Здравствуйте, netch80, Вы писали:
N>Кто читерит в C#, я не понял. Вот у меня дотнет 7.0.100-preview.1.22110.4 (из снапа убунты).
Недосмотрел, понадеявшись на единое поведение от версии к версии.
$ mcs --version
Mono C# compiler version 4.6.2.0
Хорошо, допустим, виноват древний Mono. В то же время, быстрая проверка на dotnetfiddle.net при выполнении
показывает следующие результаты:
* .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() как заявлялось в начале темы. Как оно же действительно работает, меня не сильно волнует.
Наверное ты и так знаешь, но поясню на всякий случай. parseInt конвертирует аргумент в строку. (0.000005).toString() === '0.000005', а (0.000005).toString() === '5e-7'. parseInt парсит строку до первого неправильного (в плане представления целых чисел) символа и возвращает всё, что смог напарсить. В первом случае он парсит 0, натыкается на точку и возвращает 0. Во втором случае он парсит 5, натыкается на e и возвращает 5. Если заменить parseInt на parseFloat то всё будет работать.