Знайомство з Erlang [17]
зберігаємо та працюємо з балансом користувача
в erlang та postgresql
Як ви можете знати, використання float -- числа з плаваючою комою,
неминуче приводить до похибок арифметики та округлень.
https://uk.wikipedia.org/wiki/IEEE_754
https://habr.com/ru/post/309812/
Відповідно для зберігання грошей на балансі користувача float не підходить.
На мою думку, баланс користувача краще зберігати в integer, в копійках
CREATE TABLE "test_user_balance" (
"user_id" bigint NOT NULL,
"balance" bigint NOT NULL,
PRIMARY KEY ("user_id")
);
INSERT INTO "test_user_balance" ("user_id", "balance") VALUES (1, 1000);
-- user_id = 1, balance = 1000 = $10
декілька функцій для роботи зі значеннями
%575 -> <<"5.75">>
balance_int2bin(V) ->
if V =:= 0 ->
<<"0.00">>;
V =:= 100 ->
<<"1.00">>;
V < 100 ->
erlang:list_to_binary("0." ++ erlang:integer_to_list(V));
V > 100 ->
V0 = erlang:integer_to_list(V),
VL = erlang:length(V0) - 2,
erlang:list_to_binary(string:sub_string(V0,1,VL) ++ "." ++ string:sub_string(V0,VL+1))
end.
%"5.45" -> 545
%"5" -> 500
%<<"5.45">> -> 545
%<<"5">> -> 500
input_balance2int(V) when erlang:is_list(V) ->
%list string
[R1|T] = string:split(V,"."),
case T =:= [] of
true ->
erlang:list_to_integer(R1) * 100;
_ ->
[R2|_] = T,
erlang:list_to_integer(R1) * 100 + erlang:list_to_integer(R2)
end;
input_balance2int(V) when erlang:is_binary(V) ->
%binary string
[R1|T] = binary:split(V, <<".">>),
case T =:= [] of
true ->
erlang:binary_to_integer(R1) * 100;
_ ->
[R2|_] = T,
erlang:binary_to_integer(R1) * 100 + erlang:binary_to_integer(R2)
end.
При бажанні цей код можна трішечки відрефакторити :)
Посилання
https://uk.wikipedia.org/wiki/IEEE_754
https://habr.com/ru/post/309812/