Лучшие практики для контакта с денежными суммами в C#

Редактировать: я запустил ваш код на своем конце, и примерно через 30 секунд я получил исключение TimeoutError: "A connection attempt failed because the connected party did not properly respond after a period of time". Вам необходимо обработать это исключение в своем коде, чтобы программа продолжала работать, даже если она не может подключиться:

try:
    client.connect("118.138.47.99", 1883, 60)
    client.loop_forever()
except:
    print("failed to connect, moving on")

print("rest of the code here")

Это выводит:

failed to connect, moving on
rest of the code here

Однако, используя connect() и loop_forever() не подходит для ваших нужд, так как они блокируют функции (то есть они блокируют выполнение вашего кода и не позволяют ему делать что-либо еще). С кодом выше, если клиент успешно соединяется, print("rest of the code here") никогда не будет достигнуто из-за loop_forever().

Вместо этого попробуйте использовать connect_async() в сочетании с loop_start() для подключения неблокирующим способом (т. Е. Ваша программа может продолжать выполнять другие действия при попытке подключения в фоновом режиме):

client.connect_async("118.138.47.99", 1883, 60)
client.loop_start()

print("rest of the code here")

while True:
    time.sleep(1)

[ 1125] Это выводит rest of the code here и продолжает работать бесконечно (в бесконечном цикле while) независимо от того, было ли соединение успешным или нет.

Обратите внимание, что в вашем определении on_connect() отсутствует один аргумент. Это должно быть:

on_connect(client, userdata, flags, rc)

Также было бы неплохо проверить код возврата on_connect и подписаться только в случае успешного подключения:

[113 ]

См. https://www.eclipse.org/paho/clients/python/docs/ и http://www.steves-internet-guide.com/client-connections. -python-MQTT / .

Для быстрого тестирования успешного соединения вы можете подключиться к test.mosquitto.org (см. https://test.mosquitto.org/ ).

9
задан Cœur 9 April 2017 в 09:57
поделиться

7 ответов

Вы не должны использовать числа с плавающей точкой из-за погрешностей округления. Десятичный тип должен подойти Вам.

8
ответ дан 4 December 2019 в 07:05
поделиться

Десятичное число является самым разумным типом для денежных сумм.

Десятичное число является основой с плавающей точкой 10 числовых типов с 28 + десятичные цифры точности. Используя Десятичное число, у Вас будет меньше неожиданностей, чем Вы будете с помощью основы 2 Двойных типа.

Двойное использование вдвое меньше памяти, чем Десятичное и Взаимное завещание быть намного быстрее из-за аппаратных средств ЦП для многих общих операций с плавающей точкой, но это не может представить большинство основных 10 частей (такой как 1,05) точно и имеет менее точные 15 + десятичные цифры точности. Дважды имеет преимущество большего количества диапазона (он может представить большее число и меньшие числа), который может пригодиться для некоторых вычислений, особенно некоторых вычислений статистики.

Один ответ на Ваш вопрос указывает, что Десятичное число является фиксированной точкой с 4 десятичными цифрами. Дело обстоит не так. Если Вы сомневаетесь относительно этого, заметьте, что следующая строка кода уступает 0.0000000001:

Console.WriteLine("number={0}", 1m / 10000000000m);

Сказав, все из которых, интересно отметить, что наиболее широко используемое программное обеспечение в мире для работы с денежными суммами, Microsoft Excel, использование удваивается. Конечно, они должны перейти через большое количество обручей, чтобы заставить его работать хорошо, и это все еще оставляет желать лучшего. Попробуйте эти две формулы в Excel:

  • =1-0.9-0.1
  • = (1-0.9-0.1)

Первые урожаи 0, вторые урожаи ~-2.77e-17. Excel на самом деле массажирует числа при добавлении и вычитании чисел в некоторых случаях, но не во всех случаях.

16
ответ дан 4 December 2019 в 07:05
поделиться

Я использую объект значения содержать обоих сумма (как a decimal) и валюта. Это позволяет работать с различными валютами одновременно. decimal рекомендовать тип данных за деньги в.NET.

2
ответ дан 4 December 2019 в 07:05
поделиться

Martin Fowler рекомендует использовать Денежный класс. См. ссылку для объяснения. Существует много реализаций его идеи там, или Вы могли записать свое собственное. Собственная реализация Fowler находится в Java, таким образом, он использует класс. Версии C#, которые я видел, используют структуру, которая кажется разумной.

6
ответ дан 4 December 2019 в 07:05
поделиться

Моя рекомендация состояла бы в том, чтобы использовать Десятичное число, как рекомендуется другими, если подразделение требуется. Для простого приложения счета я рекомендовал бы Целый тип. Для обоих типов я всегда работал бы над самым низким денежным наименованием. (т.е. центы в Канаде / США)

Мне действительно нравится теория Денежного вызова Fowler, добавленного @dangph.

0
ответ дан 4 December 2019 в 07:05
поделиться

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

0
ответ дан 4 December 2019 в 07:05
поделиться

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

Я когда-то провел неделю, разыскивая ошибку за 1¢, потому что SQLServer и .NET используют различные способы округлить валюты, и приложение не было согласованно в том, как он обработал определенные типы вычислений - иногда они были сделаны в SQL, иногда в .NET. Изучите "округление банкиров", если Вам интересно.

Существуют также проблемы, связанные с форматированием валют - не уверены, если необходимо иметь дело с небританскими суммами, другими языками/культурами, и т.д. но это добавит другой уровень сложности.

0
ответ дан 4 December 2019 в 07:05
поделиться
Другие вопросы по тегам:

Похожие вопросы: