Nano Hash - криптовалюты, майнинг, программирование

Математический расчет с десятичным числом неверен

У меня есть метод C#, который принимает три параметра string. После преобразования их в decimal я пытаюсь выполнить простой математический расчет. Я не понимаю, почему результат не правильный?

decimal d = MyFunction(x, y, z);


public decimal MyFunction(string x, string y, string z)
{
    decimal dx = 0;
    decimal dy = 0;
    decimal dz = 0;

    Decimal.TryParse(x, out dx);
    Decimal.TryParse(y, out dy);
    Decimal.TryParse(z, out dz);

    decimal result = dx - dz + dy;
    return result;
 }

Заранее спасибо.

25.09.2009

  • Вам нужно дать более подробную информацию: чему равны x, y, z и что вы ожидаете получить в переменной результата? 25.09.2009
  • Подумайте о том, о чем вы спрашиваете, и о той информации, которую вы нам предоставили: почему [unknownValue1] - [unknownValue2] + [unknownValue3] = [unknownValue4] неправильно? 25.09.2009
  • Если вы ожидали чего-то другого, кроме 151804.25, вы ошиблись. 25.09.2009
  • Расскажите нам, чего вы ожидаете. Может быть, мы узнаем, как должен выглядеть расчет. 25.09.2009
  • Почему вы удалили свой вклад и ожидаемый результат из вопроса? Вопрос теперь неполный и может быть отклонен. 31.01.2015

Ответы:


1

Изменить в ответ на дополнительную информацию о вопросе:
Я не вижу вашей проблемы. Я получаю 151804,25, что является правильным результатом выполнения (1186197,29 - 1260711,19) + 226318,15.

Может быть, вы запутались, потому что ожидаете, что x - z + y будет означать x - (z + y), а не (x - z) + y?
Приоритет операторов C# для - и + слева направо, поэтому это означает (х - г) + у. Если вы хотите x - (z + y), вам придется написать это так.


Вычисления с плавающей запятой часто принципиально неточны (хотя decimal работает намного лучше, чем float и double для денежного и аналогичного использования). Пример:

decimal x = 1m / 3m;
decimal y = 0;

for (int i = 0; i < 1e6; i++)
{
    y += x;
}

Результат y:

333333.33333333333333333072026

25.09.2009
  • @Joren: Игнорируя проблемы переполнения и предполагая равную точность входных и выходных данных, сложение/вычитание с плавающей запятой является абсолютно точным. 25.09.2009
  • Двоичное представление значения Decimal состоит из 1-битного знака, 96-битного целого числа и коэффициента масштабирования, используемого для деления 96-битного целого числа и указания того, какая его часть является десятичной дробью. Другими словами, это не приблизительное значение, такое как float или double. 25.09.2009
  • @Р. Бемроуз: набор действительных чисел бесконечен, в то время как набор чисел, которые могут быть точно представлены десятичной дробью, конечен, поэтому десятичная дробь по-прежнему является приближением. 25.09.2009
  • Отредактировал мой ответ, чтобы показать пример неточности decimal. Я бы не назвал это переполнением, это просто следствие ограниченной точности. Ограниченная точность очень важна для такого типа данных. 25.09.2009
  • Хотя с моей стороны было ошибкой сказать, что они никогда не точны. Это вопиющая неправда. Отредактировал и это. 25.09.2009
  • @Powerlord: в зависимости от контекста Decimal может содержать точное или неточное значение; к сожалению, нет никаких указаний на то, что он держит в любой момент. Добавление точных значений является ассоциативным в разумных пределах, но добавление неточных значений, как правило, не является ассоциативным, если только промежуточные результаты не остаются в диапазоне примерно +/- 8. 12.09.2013

  • 2

    Если результат, который вы получаете, равен нулю, возможно, TryParse не смог проанализировать строки.

    Вы должны заменить вызовы TryParse на decimal dx = Decimal.Parse(x); и посмотреть, не вызовет ли это исключение.

    Если это не проблема, мы не сможем вам помочь, пока вы не предоставите более подробную информацию.

    Чему равны x, y и z и какой результат вы получаете?

    EDIT: в ответ на дополнительную информацию, добавленную к вопросу, кажется, что все остальные правы, и проблема, вероятно, заключается в отсутствии скобок.

    25.09.2009
  • +1. Игнорирование результата вызовов TryParse означает наличие трех потенциальных точек отказа. Если строка неразборчива, значение будет равно нулю. 25.09.2009
  • Это не проблема. Нет проблем. Ответ, возвращаемый функцией Florjon, правильный. 25.09.2009
  • Ничего против вас, SLaks, но почему люди продолжают голосовать за этот ответ? Входные данные в вопросе анализируются нормально. 25.09.2009
  • Потому что я ответил до того, как он добавил ответы на вопрос. 25.09.2009

  • 3

    Кажется, я понимаю, в чем твоя проблема. Эта функция работает правильно, но внимательно посмотрите на эту строку:

    decimal result = dx - dz + dy;
    

    Возможно, вы хотели написать это:

    decimal result = dx + dz + dy;
    

    или это:

    decimal result = dx - (dz + dy);
    
    25.09.2009
  • не работать даже таким образом. кажется, что значение правильное, но когда я делаю xxxx.29 - xxxx.19, он говорит, что равен xxxx.9, это не имеет смысла. 25.09.2009
  • @Florjon: как ты это понимаешь? Когда я выполняю эту строку: 2000.29M - 1000.19M, я получаю 1000.1. 25.09.2009
  • Если первое число больше второго, то ответ правильный: 1000,29 - 2000,19 = -999,9. 25.09.2009
  • @Ralph: я думаю, вы имели в виду, что если второе число больше, чем первое ... и они ЯВЛЯЮТСЯ в этом случае: 1260711.19 › 1186197,29. 25.09.2009
  • @Dan: Верно, спасибо. Я перевернул это. Моя математика в этом случае яснее, чем мой английский. Как сказал бы вам любой математик: просто доверяйте формулам. 25.09.2009
  • @Ralph: Я думаю, ты попал прямо между глаз. Задающему вопрос нужен урок математики. 25.09.2009
  • @Ralph: Действительно, в этом случае кажется, что самая большая ошибка автора заключалась в том, что он просто не доверял компьютеру. 25.09.2009
  • @MusiGenesis: попал гвоздь между глазами? Это какой-то гвоздь ;) 25.09.2009
  • Блестящий. Я помню это выражение. :) 25.09.2009
  • Я использую это выражение так часто, что иногда я использую его, даже когда я имею в виду сказать, попал прямо в голову. Ну да ладно, половина одного, шесть десятков другого. 25.09.2009

  • 4

    Я сделал это вычисление (1186197,29 - 1260711,19 + 226318,15) три раза, и я получаю 151804,25.

    Между прочим, M в конце числа просто означает, что это Decimal.

    25.09.2009
  • Я сделал расчет с помощью Mathematica с точным символьным вычислением, и он дает 607217/4 = (607217 * 25)/(4 * 25) = 15180425/100. Думаю, мы можем быть уверены, что результат decimal правильный. ;) 25.09.2009
  • Из комментария постера к ответу MusiGenesis кажется, что он / она просто как-то запутался в самой арифметике и пытается проверить ответ вручную. 25.09.2009
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..