vak: (Знайка)
[personal profile] vak
#include <stdio.h>
int main ()
{
    if (-5.2 + 4.9 != -0.3) {
        printf("Oops!\n");
    }
    if (4.8 - 6.1 != -1.3) {
        printf("Oops!\n");
    }
    if (4.3 - 3.6 != 0.7) {
        printf("Oops!\n");
    }
}
Это мне надо было простенький тестик сварганить по работе, суммировать плавающие числа, а оно вон как боком выскочило.

nz

Date: 2023-01-14 23:22 (UTC)
From: [personal profile] nz

Зачем так сложно, 0.1 + 0.2 != 0.3 же.

C#

Date: 2023-01-15 00:40 (UTC)
dennisgorelik: 2020-06-13 in my home office (Default)
From: [personal profile] dennisgorelik
In C# floating point calculations are not precise too:
[TestMethod]
public void FloatingPointCheck()
{
	Assert.AreEqual(0.2, 0.1 + 0.1); // Passes
	Assert.AreEqual(3.0, 1.0 + 2.0); // Passes
	Assert.AreEqual(0.3, 0.1 + 0.2); // Fails
}
Edited Date: 2023-01-15 00:40 (UTC)

Re: C#

Date: 2023-01-15 16:01 (UTC)
dennisgorelik: 2020-06-13 in my home office (Default)
From: [personal profile] dennisgorelik
Is there a convenient way to use more precise representation?

Re: C#

Date: 2023-01-15 19:15 (UTC)
ircicq: (Default)
From: [personal profile] ircicq
Type `decimal` in many programming languages including C#
Although it is slower

Edited Date: 2023-01-15 19:15 (UTC)

Re: C#

Date: 2023-01-15 20:40 (UTC)
dennisgorelik: 2020-06-13 in my home office (Default)
From: [personal profile] dennisgorelik
Oh.
[personal profile] vak meant "data representation in computer memory" (floating-point double vs decimal).
I thought he meant representation/conversion of data to decimal string.

In any case, the primary way to deal with imprecision is not increasing precision, but replacing number equality comparison with [epsilon] range comparison.
Edited Date: 2023-01-15 20:41 (UTC)

Date: 2023-01-16 05:50 (UTC)
dennisgorelik: 2020-06-13 in my home office (Default)
From: [personal profile] dennisgorelik
> Hex literals work fine.

Hex interface is a good workaround.
But it may be hard to convince end users to use hex interface, right?

Date: 2023-01-14 23:30 (UTC)
From: [personal profile] ichthuss
Кто использует с плавающими типами сравнения "==" и "!=", кроме очень специальных случаев, тот сам себе злобный буратино.

Тестик, в принципе, относится к этим специальным случаям. Тут можно воспользоваться простым подходом: использовать числа, кратные 1/2^n, где n < 24. Например, 0.25+0.375
Edited Date: 2023-01-14 23:35 (UTC)

Date: 2023-01-14 23:56 (UTC)
perdakot: (Default)
From: [personal profile] perdakot
Я хардвер проверя

Тогда, наверное, надо float раздербанить на знак, экспоненту и мантиссу (целые) и сравнивать их, а не плавучку.

Date: 2023-01-15 01:19 (UTC)
perdakot: (Default)
From: [personal profile] perdakot
Это без разницы, сравнивать три поля по отдельности или всё слово целиком.

Не может быть, что копиляторы могут сделать мантиссу немного разную у плавучего литерала?

Date: 2023-01-15 00:47 (UTC)
ircicq: (Default)
From: [personal profile] ircicq
Есть полезная статья G. Steele, Jon L. White - How to print floating-point numbers accurately

Там про десятичную печать, но алгоритм можно применить и для сравнения.

Date: 2023-01-15 01:29 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Вечная тема. вообще говоря, вопрос равенства вещественных чисел и теоретически сложен. Проще считать, что это не эквациональная теория.

Date: 2023-01-15 01:39 (UTC)
juan_gandhi: (Default)
From: [personal profile] juan_gandhi

Ну ты прям физик.

Мы не такие. Я когда-то эмулятор FPP писал, так обнаружил, что могу вполне, на тех 80 битах, выдать точность выше, чем настоящий FPP гонит. Там же еще один запасной бит был, не в регистрах, а в процессе вычислений.

Date: 2023-01-15 02:07 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Используй шестнадцатеричные вещественные константы типа 0x1p-1. Их уже давно завезли в С и C++.

Date: 2023-01-15 03:21 (UTC)
archaicos: Шарж (Default)
From: [personal profile] archaicos
Если он на плюсах, то стандартная библиотека конвертнёт, надо лишь распарсить.
Если на питоне, то надо поискать, может тоже простое решение. Хотя, шестнадцатеричное можно и самому преобразовать, т.к. сложное уже отсутствует.

если на плюсах ...

Date: 2023-01-15 04:08 (UTC)
From: [personal profile] h1uke
или на Питоне лезть на этот уровень --
то поневоле вспоминаешь древнюю формулу: "со свиным рылом в калашный ряд" :)

будто эти ваши плюсы, или там Питон - это не программы, написанные изначально на "лысом С"

Date: 2023-01-15 05:53 (UTC)
sobriquet9: (Default)
From: [personal profile] sobriquet9
Есть же DBL_EPSILON и std::numeric_limits::epsilon().

Date: 2023-01-15 06:40 (UTC)
From: [personal profile] dijifi
В начале моей карьеры видел я квадратный корень из четырех равный единице, но только для инструкции single precision. Глючный микрокод у железа. Так, вспомнилось.

Date: 2023-01-15 08:02 (UTC)
From: [personal profile] dijifi
В начале моей карьеры видел я квадратный корень из четырех равный единице, но только для инструкции single precision. Глючный микрокод у железа. Так, вспомнилось.

Date: 2023-01-15 14:22 (UTC)
sobriquet9: (Default)
From: [personal profile] sobriquet9
Так оно и получается. Даже с дробями всё точно, только в двоичной системе. Хотите, чтоб в десятичной было точно - переделайте вычислитель, чтоб он считал в десятичной системе. Такое вроде уже ж было, какие-то компьютеры внутри себя считали всё в BCD.

А ещё лучше сразу в шестидесятиричной, как у древних египтян. Тогда на три тоже делить удобно будет.

Date: 2023-01-18 11:08 (UTC)
waqur: (Default)
From: [personal profile] waqur
Не зря в банковской сфере так популярен COBOL, у которого развитая система целочисленных типов фиксированной ширины в десятичном представлении. Банкиры ещё в 70-е были не в восторге от всех этих фокусов с округлением вещественных чисел с плавающей точкой.