Округления с операторами арифметических действий и присваивания
Хочу не просто x += 1.22000001 писать, а с округлением. Типа такого
double x = 1.5;
x += 1.22000001;
но чтобы иксу присвоилось уже округлённое значение, чтобы избавиться от погрешностей при работе с double.
Если вызвать Math.Round справа
x += Math.Round(1.22000001, 2)
то получим просто округлённое значение 1.22000001, а потом будет выполнена операция присвоения с возможной ошибкой вычислений.
Насколько я понял, с Math.Round такие операторы использовать нельзя, и надо писать полную запись
x = Math.Round(x + 1.22000001, 2);
Или всё же есть способ?
У вас просто случайно так получилось. Результат зависит не только от того, что непосредственно в Round придёт в виде парамера, но и от х. Параметр вы округлили, а х - нет.
Там погрешность округления в последнем разряде при переводе из двоичной системы в десятичную. Поэтому надо периодически округлять до нужной точности. У меня точность с запасом (три знака после запятой, и сами числа не больше 6-7 знаков), и в принципе можно округлять лишь при выводе, при строковом форматировании. Но всё равно не нравится периодически выхватывать эти девятки и единички. Кроме того, при определённом MidpointRounding всякие х,9999999 и х,00000001 легко превращаются не в то, что нужно.
ну так ты и объяснял русским языком, в чем твоя проблема
для таких вещей был придуман тип Decimal
Кроме того, при определённом MidpointRounding всякие х,9999999 и х,00000001 легко превращаются не в то, что нужно.
это ты его используешь не по назначению
Decimal много весит
Тест проект есть, на сколько мегабайт разница?
https://stackoverflow.com/questions/803225/when-should-i-u...
Как-то плохо ты год начал, какой-то поток сознания. Я же говорил, сбегай в дежурную аптеку.
А что мешает пользовать public static double operator +(double left, double right)?
https://learn.microsoft.com/en-us/dotnet/csharp/language-r...
А смысл операторы перегружать? Там же ошибка возникает не просто в вычислениях, а и в хранении. Данные хранятся в битах, а многие десятичные числа с плавающией заяптой в битах точно не представимы - приходится округлять. Сколько ни приводи типы, ни перегружай операторы - этот "дребезг" последнего разряда by design.
Вобщем, я пишу как и сказал в начале x = Math.Round(x + 1.22000001, 2); Просто хотел, чтобы было коротко и красиво.
Данных примерно до несколько десятков мегабайт может дойти. Вроде немного, даже если удвоить. И даже для мобильных телефонов должно хватить. Но меня смущает, что сериализатор все эти типы представляет как float.
Тут вообще советуют в строках хранить при сериализации
https://stackoverflow.com/questions/35709595/why-would-you...
А смысл операторы перегружать?
"Результат зависит не только от того, что непосредственно в Round придёт в виде парамера, но и от х. Параметр вы округлили, а х - нет."
Для начала неясна проблема в принципе. Если нужна большая точность, то Decimal
иначе проблемы будут
http://blog.ygrenier.com/2017/10/dotnet-differences-floati...
https://discussions.unity.com/t/c-floating-point-confusion...
https://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg...
Есть алгоритм Кэхэна для суммы ряда (https://en.wikipedia.org/wiki/Kahan_summation_algorithm), сохраняющий более высокую точность при работе с числами с плавающей запятой.
В англ. варианте статьи описан более корректный алгоритм Ноймаера.
В принципе, надо просто написать доп. функцию суммирования чисел по указанным алгоритмам, и тогда результат будет с максимальной точностью, которую возможно получить при использовании чисел в формате с плавающей запятой.
Round надо будет применять уже к результату суммирования.
Если же надо прям "абсолютную" точность, то надо использовать, как уже сказали, decimal или методы нормализации (чтобы не работать с машинным представлением вещественных чисел, так как потеря точности там уже на уровне представления появляется. Она хорошая, погрешность, но все равно есть)
Округления с операторами арифметических действий и присваивания
Runden zu Integer. In der Welt der Pixel sind ganze Zahlen gefragt.
let x = 17.4999;
let y = Math.round(x); // Auf- oder Abgerundet auf 17
Rundet auf ab .5, rundet ab bis .49999
Runden auf Nachkommastellen. Für das Runden auf 2 Nachkommastellen braucht Javascript einen Trick:
Math.round (217.4325 * 100) / 100; // 217.43
Einfacher geht das Runden in Javascript mit toFixed:
let num = 9.7433789;
let n = num.toFixed(2);
Noch mal zurück auf Runden mit Math. Schluss mit 97 oder 49 Cent: Aufrunden zu 5 oder 0 in der zweiten Kommastelle
let cents = 1017.721987;
let fünfcents = (Math.ceil(cents*20)/20).toFixed(2);
console.log ("fünfcents " + fünfcents)
fünfcents 1017.75
Ну что, погромисты, слабо такой пример решить, как в начале видео, без просмотра до конца и подсказок?
Не знаю, как сейчас это требуют решать, а в моё время уже в задании писали (подсказка) - "раскройте скобки и упростите". Т.е. уже подсказал, что сначала нужно раскрыть скобки. Ну и вспомнить (уже совсем большая подсказка), чем смешанная дробь отличается от простой дроби со множителем.