PHP와 MySql에서 화폐 가치를 다루는 방법?


16

MySQL 데이터베이스 위에 PHP로 작성된 거대한 레거시 코드를 상속했습니다. 내가 주목 한 것은 응용 프로그램 doubles이 데이터 저장 및 조작에 사용한다는 것 입니다.

이제 나는 double반올림 오류로 인해 화폐 운영에 적합하지 않은 방법 을 언급하는 수많은 게시물을 보았습니다 . 그러나 아직 화폐 가치를 PHP 코드에서 처리하고 MySQL 데이터베이스에 저장하는 방법에 대한 완전한 솔루션을 찾지 못했습니다.

PHP로 돈을 처리 할 때 가장 좋은 방법이 있습니까?

내가 찾고있는 것 :

  1. 데이터베이스에 데이터를 어떻게 저장해야합니까? 열 유형? 크기?
  2. 정상적인 덧셈, 뺄셈에서 데이터를 어떻게 처리해야합니까? 곱셈 또는 나눗셈?
  3. 언제 값을 반올림해야합니까? 반올림이 가능한 경우 얼마나 되나요?
  4. 큰 금전적 가치와 낮은 금전적 가치를 다루는 데 차이가 있습니까?

참고 : 일상 생활에서 돈 가치가 발생할 수있는 방법에 대한 매우 단순화 된 샘플 코드 (다양한 보안 문제는 단순화를 위해 무시되었습니다. 물론 실제로는 내 코드를 다음과 같이 사용하지 않습니다) :

$a= $_POST['price_in_dollars']; //-->(ex: 25.06) will be read as a string should it be cast to double?
$b= $_POST['discount_rate'];//-->(ex: 0.35) value will always be less than 1
$valueToBeStored= $a * $b; //--> any hint here is welcomed 

$valueFromDatabase= $row['price']; //--> price column in database could be double, decimal,...etc.

$priceToPrint=$valueFromDatabase * 0.25; //again cast needed or not?

이 샘플 코드를 사용하여 더 많은 사용 사례를 이끌어 내고 문자 그대로 사용하지 않기를 바랍니다.

보너스 질문 Doctrine 또는 PROPEL과 같은 ORM을 사용하는 경우 코드에서 돈을 사용하는 것이 얼마나 다른가요?


1
나는 PHP를 알고 있지만 용어를 아는 것이 구글 - Fu는 이러한 시나리오에서 매우 유용하지 않습니다, 당신이 찾고있는 용어로 응답 구글되는 "임의 정밀도"입니다 php.net/manual/en/book.bc.php은
Jimmy Hoffa

1
@Jimmy Hoffa : 임의 정밀도는 일반적으로 필요한 것이 아니며, 소수를 정확하게 표현하고 사용할 수있는 것입니다. 물론 decimalC # 의 유형은 정밀도가 제한적이지만 금전적 가치에 완벽하게 적합합니다.
Michael Borgwardt

1
@MichaelBorgwardt 맞아요. 합리적인 언어는 잊어 버렸기 때문에 많은 언어가 없기 때문입니다. 잘 했어
Jimmy Hoffa

통화 및 레거시 코드로 많은 작업을 한 결과 정수로 저장하고 달러 대신 센트를 사용한다고 가정합니다. 그러나 32 개의 정수는 놀랍게도 적은 양을 보유 할 수 있습니다.
Pieter B

제쳐두고, 게시되는 가격과 할인을 보여주는 샘플 코드는 나를 무섭게합니다. 다행히도 실제 사용량을 반영하지 않기 때문에 간소하지만 액면가에서는 숨겨진 필드 등을 다시 게시하여 항목의 가격을 알려주는 브라우저를 신뢰하는 것처럼 보입니다.
Carson63000

답변:


6

PHP / MySQL로 숫자를 처리하는 것은 상당히 까다로울 수 있습니다. decimal (10,2)을 사용하고 숫자가 더 길거나 정밀도가 높은 경우 (DB 서버에 적절한 모드를 설정하지 않은 경우) 오류없이 잘립니다.

큰 값이나 높은 정밀도 값을 처리하기 위해 BCMath 와 같은 라이브러리를 사용할 수 있으므로 큰 숫자에서 기본 작업을 수행하고 필요한 정밀도를 유지할 수 있습니다.

정확히 어떤 계산을 수행할지 확실하지 않지만 프로세스를 통해 올바른 정밀도를 사용하지 않으면 (0.22 * 0.4576) + (0.78 * 0.4576)이 0.4576과 같지 않다는 점을 명심해야합니다.

MySQL에서 DECIMAL의 최대 크기는 65이므로 어떤 목적에도 충분해야합니다. DECIMAL 필드 유형을 사용하면 ORM 사용 또는 일반 PDO / mysql (i)에 관계없이 문자열로 리턴됩니다.

데이터베이스에 데이터를 어떻게 저장해야합니까? 열 유형? 크기?

필요한 정밀도로 결정하십시오. 환율을 사용하는 경우 소수점 이하 네 자리 이상이 필요합니다.

정상적인 덧셈, 뺄셈에서 데이터를 어떻게 처리해야합니까? 곱셈 또는 나눗셈?

BCMath를 사용하여 저장면에 놓고 플로트를 사용 하는 것이 좋지 않은 이유

언제 값을 반올림해야합니까? 반올림이 가능한 경우 얼마나 되나요?

화폐 가치의 경우 일반적으로 소수점 이하 두 자리를 사용할 수 있지만 환율을 사용하는 경우 더 많이 필요할 수 있습니다.

큰 금전적 가치와 낮은 금전적 가치를 다루는 데 차이가 있습니까?

큰 의미에 따라 다릅니다. 높은 정밀도로 숫자를 처리하는 것에는 분명히 차이가 있습니다.


9

간단한 해결 방법은 정수로 저장하는 것입니다. 99.99가 9999로 저장됩니다. 이것이 작동하지 않는 경우 (그리고 이것이 잘못된 선택 일 수있는 여러 가지 이유가있는 경우) 유형 Decimal을 사용할 수 있습니다. mysql 측의 http://dev.mysql.com/doc/refman/5.0/en/precision-math-decimal-changes.html PHP 쪽에서 나는 이것이 https : //.com/questions/3244094/decimal-type-in-php 발견했습니다 .

보너스 질문 : 말하기 어렵다. orm은 선택한 데이터 유형에 따라 작동합니다. 나는 당신이 도움을주기 위해 추상화로 물건을 할 수 있다고 말하고 싶지만이 특정 문제는 단순히 ORM으로 이동하여 해결되지 않습니다.


1
FWIW, Drupal Commerce는 9999 트릭을 사용하여 가격을 저장합니다.
Florian Margaine

1
"이것이 나쁜 선택이 될 수있는 많은 이유가 있습니다." 당신은이 연습에 몇 가지 문제를 공유하겠습니까?
Songo

2
@Songo은 다음을 참조하십시오 floating-point-gui.de/formats/integer
마이클 Borgwardt

@MichaelBorgwardt 정보 주셔서 감사합니다, 송노 지연에 대해 죄송합니다, 허리케인은 우리를 꺼내 :)
Ominus

3

나는 이것에 내 경험을 넣으려고 노력할 것이다.

내가 찾고있는 것 :

데이터베이스에 데이터를 어떻게 저장해야합니까? 열 유형? 크기?

나는 DECIMAL(10,2)문제없이 mysql 에 사용 했다 (8 개의 완성과 2 개의 소수점 == 99.999.999,99 == 엄청난 양), 이것은 당신이 다루어야 할 돈 범위에 달려 있습니다. 상당한주의를 기울여야합니다 (예 : OS 최대 부동 소수점 값). 소수 부분에서는 자르거나 반올림하지 않도록 2 개의 값을 사용합니다. 돈을 벌 때 더 많은 소수점이 필요한 경우는 거의 없습니다 (이 경우 사용자가 모든 것을 다룰 수 있는지 확인해야합니다. 그렇지 않으면 쓸모없는 데이터입니다)

정상적인 덧셈, 뺄셈에서 데이터를 어떻게 처리해야합니까? 곱셈 또는 나눗셈?

하나의 통화 및 교환 테이블 (날짜 포함)로 작업하십시오. 이렇게하면 항상 정확한 금액이 저장됩니다. 추가 사항 : 전체 값을 저장하고 계산 결과가 포함 된보기를 만듭니다. 이것은 당신이 즉석에서 값을 고정하는 데 도움이 될 것입니다

언제 값을 반올림해야합니까? 반올림이 가능한 경우 얼마나 되나요?

다시, 시스템 머니 범위에 따라 다릅니다. 환전소의 혼란에 빠지지 않는 한 항상 KISS 용어로 생각하십시오.

큰 금전적 가치와 낮은 금전적 가치를 다루는 데 차이가 있습니까?

OS 및 프로그래밍 언어에 따라 항상 최대 값과 최소값을 확인해야합니다


대답을 주셔서 감사합니다,하지만 난처럼 핸들 뭔가가 있다면 $valueToBeStored= $a * $b;경우 $a그리고 $b나는 그들이에 캐스트 할 것이라고 생각 데이터베이스에서 소수로 모두 읽어 doublePHP의 오른쪽은? 숫자에 영향을 주나요?
Songo

$a그리고 $bdb에서 가져온 것입니까? 따라서 제 예제 $valueToBeStored에서는 항상 소스 $a$b데이터 가 있기 때문에 저장하지 않아도됩니다 . 따라서 함수 적으로 값을 프로그래밍 방식으로 작업하거나 열 결과로 mysql보기를 만들 수 있습니다. 이렇게하면 값을 변경해야하는 경우 여러 장소 수정에 대해 걱정할 필요가 없습니다 (오류가 발생하기
쉬움
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.