Computer >> 컴퓨터 >  >> 프로그램 작성 >> Ruby

루비의 통화 계산

통화에 관계없이 돈은 부동 소수점 숫자처럼 보입니다. 하지만 수레를 통화로 사용하는 것은 실수입니다.

부동 소수점 숫자(따라서 float 개체)는 정의에 따라 기본 아키텍처의 배정도 부동 소수점 표현 특성을 사용하는 부정확한 실수입니다. 정확하지 않은 숫자는 회계사를 불행하게 만듭니다.

이 기사에서는 Ruby 및 Rails에서 화폐 데이터를 처리하는 데 사용할 수 있는 옵션을 해결하는 데 도움이 되는 몇 가지 간단한 예를 안내합니다.

플로트란 무엇입니까?

우리가 말했듯이 float 객체는 다른 산술을 가지고 있습니다. 이것이 그들이 부정확한 숫자인 주된 이유입니다. 특히 Ruby(대부분의 언어와 마찬가지로)는 부동 소수점을 나타내기 위해 고정된 수의 이진 숫자를 사용하기 때문입니다. 즉, Ruby는 부동 숫자를 10진수에서 2진수로 또는 그 반대로 변환합니다.

실수(10진수라고도 함)의 이진 표현에 대해 자세히 알아볼 때 일부는 정확하게 표현할 수 없으므로 시스템이 반올림하는 방법만 남아 있습니다.

정기적인 십일조와 같은 일반적인 수학 구조를 미리 생각하고 고려하면 pi 예를 들어 숫자는 무한합니다. 부동 소수점은 일반적으로 최대 32비트 또는 64비트의 정밀도를 보유할 수 있습니다. 즉, 한계에 도달하면 숫자가 잘립니다.

고전적인 예를 분석해 보겠습니다.

1200 * (14.0/100)

이것은 숫자의 백분율을 계산하는 간단한 방법입니다. 1200의 14퍼센트는 168이어야 합니다. 그러나 Ruby 내에서 이 실행의 결과는

1200 * (14.0/100)
=> 168.00000000000003

그러나 공식에 0.1%만 추가하면 다른 결과가 나타납니다.

1200 * (14.1/100)
=> 169.2

또는 round할 수 있습니다. 원하는 소수점 이하 자릿수를 정의하여 가능한 가장 가까운 값으로 값:

(my_calculation).round(2)

실제로 더 복잡한 계산의 경우, 특히 이러한 값을 비교하는 경우에는 보장되지 않습니다.

그 이면의 실제 과학을 이해하는 데 관심이 있다면 Oracle의 부록:모든 컴퓨터 과학자가 부동 소수점 산술에 대해 알아야 할 사항을 읽는 것이 좋습니다. 부동 소수점 숫자의 부정확한 특성 뒤에 숨겨진 이유를 자세히 설명합니다.

신뢰할 수 있는 BigDecimal

다음 코드 스니펫을 고려하십시오.

require "bigdecimal"
BigDecimal("45.99")

이 코드는 전자 상거래 장바구니 금액을 수용하는 실제 논리를 쉽게 나타낼 수 있습니다. 결국 조작되는 실제 값은 예를 들어 45.9989 또는 45.99000009 대신 항상 45.99가 됩니다.

이것이 BigDecimal의 정확한 특성입니다. . 일반적인 산술 계산의 경우 float 같은 방식으로 수행됩니다. 그러나 예측할 수 없으므로 사용할 위험이 있습니다.

BigDecimal로 실행될 때 , 이전 섹션에서 수행한 것과 동일한 백분율 계산 결과

require "bigdecimal"
(BigDecimal(1200) * (BigDecimal(14)/BigDecimal(100))).to_s("F")
=> 168.0

이것은 irb에서 빠른 실행을 허용하는 짧은 버전일 뿐입니다. 콘솔.

원래 BigDecimal을 직접 인쇄할 때 개체, 당신은 그것의 과학적 표기법을 얻을 것입니다, 그것은 우리가 여기서 원하는 것이 아닙니다. to_s 메서드는 형식 설정으로 인해 주어진 인수를 수신하고 BigDecimal의 동등한 부동 값을 표시합니다. 이 주제에 대한 자세한 내용은 Ruby 문서를 참조하세요.

소수점 이하 자릿수 제한을 결정해야 하는 경우에는 truncate가 있습니다. 작업을 수행하는 방법:

(BigDecimal(1200) * (BigDecimal("14.12")/BigDecimal(100))).truncate(2).to_s("F")
=> 169.44

RubyMoney 프로젝트

RubyMoney는 이러한 문제를 생각하여 만들어졌습니다. Ruby 생태계에서 돈 데이터를 조작할 수 있는 훌륭한 라이브러리를 제공하여 개발자의 삶을 용이하게 하는 것을 목표로 하는 Ruby 개발자의 오픈 소스 커뮤니티입니다.

이 프로젝트는 7개의 라이브러리로 구성되어 있으며 그 중 3개가 가장 중요합니다.

  • Money:돈 및 통화 변환을 처리하기 위한 Ruby 라이브러리입니다. 웹용인지 여부에 관계없이 강력하고 현대적인 애플리케이션에서 비용을 처리할 수 있는 몇 가지 객체 지향 옵션을 제공합니다.
  • Money-rails:모든 money를 혼합한 Ruby on Rails용 RubyMoney 통합 Rails의 유연성을 갖춘 의 라이브러리 기능
  • 수익 창출:다양한 개체를 money으로 변환하는 라이브러리 사물. 예를 들어, 많은 문자열 구문 분석을 처리하는 애플리케이션을 위한 보조 라이브러리처럼 작동합니다.

이 프로젝트에는 4개의 다른 흥미로운 라이브러리가 있습니다.

  • EU_central_bank:유럽 중앙 은행의 공시 환율을 사용하여 환율 계산을 돕는 라이브러리입니다.
  • Google_currency:참조로 Google 환율을 사용하는 통화 변환을 위한 흥미로운 라이브러리입니다.
  • Money-collection:money의 합계/최소/최대값을 정확하게 계산하기 위한 보조 라이브러리 개체.
  • Money-heuristics:money gem의 문자열 입력에 대한 경험적 분석을 위한 모듈입니다.

"돈" 보석

가장 유명한 것부터 시작해 보겠습니다:돈의 보석. 주요 기능은 다음과 같습니다.

  • money 가치, 통화 및 소수점과 같은 관련 통화 정보를 보유하는 클래스입니다.
  • Money::Currency라는 또 다른 클래스 개발자가 사용하는 화폐 단위에 대한 정보를 래핑합니다.
  • 기본적으로 앞서 언급한 오류를 피하기 위해 부동 소수점 숫자가 아닌 정수로 작동합니다.
  • 한 통화에서 다른 통화로 돈을 교환할 수 있는 기능, 정말 멋집니다.

그 외에도 프로젝트 내의 다른 모델과 마찬가지로 화폐 데이터를 조작하기 위해 일관되고 객체 지향적인 구조가 제공하는 높은 유연성도 얻을 수 있습니다.

사용법은 매우 간단합니다. 적절한 gem을 설치하기만 하면 됩니다.

gem install money

고정 금액과 관련된 간단한 예는 다음과 같습니다.

my_money = Money.new(1200, "USD")
my_money.cents #=> 1200
my_money.currency #=> Currency.new("USD")

보시다시피 돈은 센트를 기준으로 표시됩니다. 1200센트는 12달러에 해당합니다.

BigDecimal에서 했던 것처럼 이러한 객체를 가지고 놀고 몇 가지 기본적인 수학을 할 수도 있습니다. 예를 들어,

cart_amount = Money.new(10000, "USD") #=> 100 USD
discount = Money.new(1000, "USD") #=> 10 USD

cart_amount - discount == Money.new(9000, "USD") #=> 90 USD

흥미롭지 않습니까? 이것이 우리가 언급한 객체의 특성입니다. 코딩할 때 표현력이 없고 평범한 숫자가 아니라 금전적 가치를 조작하는 것처럼 느껴집니다.

통화 변환

자체 환율 시스템이 있는 경우 교환 은행 개체를 통해 통화 변환을 수행할 수 있습니다. 다음을 고려하십시오.

Money.add_rate("USD", "BRL", 5.23995)
Money.add_rate("BRL", "USD", 0.19111)

값을 교환해야 할 때마다 다음 코드를 실행할 수 있습니다.

Money.us_dollar(100).exchange_to("BRL") #=> Money.new(523, "BRL")

수행하려는 모든 산술 및 비교 평가에도 동일하게 적용됩니다.

iso_code와 같이 제공된 통화 속성에 대한 자세한 내용은 문서를 참조하세요. (해당 통화의 국제 3자리 코드를 반환) 및 decimal_mark (값과 화폐 데이터의 비율 사이의 문자) 등.

아, 거의 잊어버렸습니다. money gem을 설치하면 BigDecimal에 액세스할 수 있습니다. to_money라는 메서드 자동으로 변환을 수행합니다.

"수익 창출" 보석

RubyMoney 프로젝트 내에서 각 라이브러리가 수행하는 역할을 이해하는 것이 중요합니다. 다른 Ruby 객체(String , 예) Money로 , monetize 당신이 찾고있는 것입니다.

먼저 gem 종속성을 설치하거나 Gemfile에 추가해야 합니다. :

gem install monetize

분명히 money 도 설치해야 합니다.

parse 이 방법은 다른 형식의 화폐 데이터를 수신할 때도 매우 유용합니다. 예를 들어,

Money.parse("£100") == Money.new(100, "GBP") #=> true

이 구문 분석 방법을 사용하는 시나리오는 제한되어 있지만 HTTP 요청에서 통화 코드와 함께 형식이 지정된 값을 수신할 때 매우 유용할 수 있습니다. 웹에서는 모든 것이 텍스트이므로 문자열에서 money로 변환 매우 유용할 수 있습니다.

그러나 시스템이 값을 조작하는 방법과 어떻게든 해킹될 수 있는지 주의하십시오. 금융 시스템은 귀하가 받는 가치가 해당 거래의 실제 가치임을 보장하기 위해 항상 여러 보안 계층으로 덮여 있습니다.

"monetize-rails" 보석

이것은 동일한 자금 조작 작업을 처리하지만 Rails 앱 내에서 처리하는 라이브러리입니다.

Rails와 함께 작동하도록 두 번째 라이브러리가 필요한 이유는 무엇입니까? 글쎄, 당신은 확실히 money을 사용할 수 있습니다 일반 수학 연산을 위한 Rails 프로젝트 내에서 gem만 사용할 수 있습니다. 그러나 Rails 구조가 money와 통신해야 하는 경우에는 제대로 작동하지 않습니다. 의 기능입니다.

다음 예를 고려하십시오.

class Cart < ActiveRecord::Base
  monetize :amount_cents
end

이것은 실제적이고 기능적인 Rails 모델 객체입니다. 데이터베이스(다른 모델 속성 이름을 원할 때 별칭 포함), Mongoid, REST 웹 서비스 등과 함께 사용할 수 있습니다.

지금까지 우리가 접촉한 모든 기능이 이 보석에도 적용됩니다. 일반적으로 실행하려면 추가 설정만 필요하며 config/initializers/money.rb에 추가해야 합니다. 파일:

MoneyRails.configure do |config|

  # set the default currency
  config.default_currency = :usd

end

이렇게 하면 기본 통화가 제공한 통화로 설정됩니다. 그러나 개발 중에 교환 변환을 수행하거나 모델 전체에서 둘 이상의 통화를 처리해야 할 가능성이 있습니다.

그렇다면 money-rails 모델 수준 통화 정의를 구성할 수 있습니다.

class Cart < ActiveRecord::Base

  # Use GPB as model level currency
  register_currency :eur

  monetize :amount_cents, as "amount"
  monetize :discount_cents, with_currency: :eur

  monetize :converted_value, with_currency: :usd

end

모든 것이 설정되면 프로젝트와 함께 돈 유형을 사용하기가 정말 쉽습니다.

마무리

이 블로그 게시물에서는 Ruby 및 Rails 생태계 내에서 금전적 가치를 처리하는 데 사용할 수 있는 몇 가지 옵션을 살펴보았습니다. 몇 가지 중요한 사항이 아래에 요약되어 있습니다.

  • 부동수 계산, 특히 화폐 데이터를 나타내는 경우 BigDecimal로 이동하세요. 또는 money 인스턴스.
  • 개발 과정에서 더 이상의 불일치를 피하기 위해 하나의 시스템만 고수하십시오.
  • money 라이브러리는 전체 RubyMoney 시스템의 핵심이며 매우 강력하고 간단합니다. Money-rails Rails 애플리케이션과 동일한 버전이며 monetize 모든 값에서 Money로 구문 분석해야 할 때마다 필요합니다. 개체.
  • Float 사용 금지 . 앱이 지금 아무 것도 계산할 필요가 없더라도 미래에는 조언 없는 개발자가 계산할 가능성이 있습니다. 당신이 그것을 막지 못할 수도 있습니다.

공식 문서는 항상 필수 항목이어야 함을 기억하십시오. BigDecimal은 훌륭한 설명과 사용법으로 가득 차 있으며 RubyMoney gem 프로젝트도 마찬가지입니다.