DECIMAL для Pawn.
#1

Всем привет.
Из-за того что я использую для своего сервера центы испытываю проблемы с большими числами. Проблема в том что если у игрока 12345678.95$ в БД сохранится только 12345678.00. Что бы решить эту проблему я начал искать по форому и наткнулся на две темы: Надеялся что они исправят мою проблему, но не тут то было.

Подключил все инклуды с ссылок выше и еще одну функцию автором которая является eXeGOODER.
PHP Code:
#include <a_samp>
#include <sscanf2>
#include <cash>
main()
{
    new 
FloatfFloat 12345678.96;
    new 
dollarcent;
    
printf(FormatNumber(fFloat2,',','.')); //formatnumber
    
printf(FormatNumber(fFloat,0)); //formatnumber
    
    
DecimalPoint(fFloat); // Decimal Point
    
    
Cash_Truncate(fFloatdollarcent); //by eXeGOODER
    
    
printf("Simple: %.2f",fFloat); // Обычный Float
}
stock Cash_Truncate(Floatcash, &dollar, &cent)
{
    new 
tmp[16];
    
format(tmpsizeof tmp"%f"cash);
    
printf("\nCash_Truncate: %s",tmp);
    
    
sscanf(tmp,"p<.>dd",dollar,cent);
    
    
printf("Cash_Truncate: %d.%d\n",dollar,cent);
}
stock DecimalPoint(Float:money)
{
    new 
str[16];
    if(
money >= 0)
    {
            
format(strsizeof(str), "%.2f$"money);
            if(
1000 <= money 10000strins(str","2sizeof(str));
            else if(
10000 <= money 100000strins(str","3sizeof(str));
            else if(
100000 <= money 1000000strins(str","4sizeof(str));
            else if(
1000000 <= money 10000000) { strins(str","2sizeof(str)); strins(str","6sizeof(str)); }
            else if(
10000000 <= money 100000000) { strins(str","3sizeof(str)); strins(str","7sizeof(str)); }
            else if(
100000000 <= money 1000000000) { strins(str","4sizeof(str)); strins(str","8sizeof(str)); }
            else if(
money >= 1000000000) { strins(str","2sizeof(str)); strins(str","6sizeof(str)); strins(str","10sizeof(str)); }
            
printf("%.2f",money);
    }
    else
    {
            
format(strsizeof(str), "-%.2f$"money-(money*2));
            if(-
1000 >= money > -10000strins(str","3sizeof(str));
            else if(-
10000 >= money > -100000strins(str","4sizeof(str));
            else if(-
100000 >= money > -1000000strins(str","5sizeof(str));
            else if(-
1000000 >= money > -10000000) { strins(str","3sizeof(str)); strins(str","7sizeof(str)); }
            else if(-
10000000 >= money > -100000000) { strins(str","4sizeof(str)); strins(str","8sizeof(str)); }
            else if(-
100000000 >= money > -1000000000) { strins(str","5sizeof(str)); strins(str","9sizeof(str)); }
            else if(
money <= -1000000000) { strins(str","3sizeof(str)); strins(str","7sizeof(str)); strins(str","11sizeof(str));}
    }
    return 
str;

На выходе мы получаем это:


Теперь уменьшаем число до 567891.34. На выходе получает это:

Уже всё по лучше.

Играя с числами я понял что после 7999999.74 ни одна из функций не выводит числа после точки.
Пример: 7999999.75 = 8000000.00

Вопрос: Можно ли как то сделать DECIMAL для PAWN что бы всё работало правильно?

P.S: Так-же есть вариант что при использования плагинов можно добиться нормальной работы Float-a, но у меня недостаточно знаний для этого.
Reply
#2

1 целочисленная ячейка под доллары, другая - под центы, не?
Reply
#3

Quote:
Originally Posted by Mutha_X
View Post
1 целочисленная ячейка под доллары, другая - под центы, не?
Думал об этом, но не практично...
Reply
#4

Тогда храните вообще все в центах, если экономика позволяет.
Reply
#5

Quote:
Originally Posted by stabker
View Post
Тогда храните вообще все в центах
Я не совсем понял то что Вы имели ввиду.

У меня в БД ячейка что отвечает за деньги DECIMAL (11,2)
Reply
#6

Тогда 2 переменных на запись в центах, в БД 1 столбец типа BIGINT в центах + плагин с форматированием в текст 8байтового целого числа и разбиением его на 2 int. Тема с подобным делом уже была, вам остаётся лишь дополнить делением(по модулю) на 100 для извлечения долларов (центов).
Reply
#7

Quote:
Originally Posted by Mutha_X
View Post
Тогда 2 переменных на запись в центах, в БД 1 столбец типа BIGINT в центах + плагин с форматированием в текст 8байтового целого числа и разбиением его на 2 int. Тема с подобным делом уже была, вам остаётся лишь дополнить делением(по модулю) на 100 для извлечения долларов (центов).
Идея была в том что бы найти способ сделать DECIMAL под PAWN, как у C# к примеру: https://docs.microsoft.com/ru-ru/dot...ywords/decimal
А не найти альтернативные решения ему.
Reply
#8

Quote:
Originally Posted by Johhnyllll
View Post
Идея была в том что бы найти способ сделать DECIMAL под PAWN, как у C# к примеру: https://docs.microsoft.com/ru-ru/dot...ywords/decimal
А не найти альтернативные решения ему.
Т.е. вариант что это невозможно вы вообще не рассматриваете?
Reply
#9

Quote:
Originally Posted by Johhnyllll
View Post
Идея была в том что бы найти способ сделать DECIMAL под PAWN, как у C# к примеру: https://docs.microsoft.com/ru-ru/dot...ywords/decimal
А не найти альтернативные решения ему.
Сначала вы говорите, что решение с 2-мя переменными (64 бит) для вас избыточно, теперь говорите, что 128 бит в самый раз, если не мало.
Reply
#10

Quote:
Originally Posted by Stepashka
View Post
Т.е. вариант что это невозможно вы вообще не рассматриваете?
Я задал вопрос:
Quote:
Originally Posted by Johhnyllll
View Post
Вопрос: Можно ли как то сделать DECIMAL для PAWN что бы всё работало правильно?
Значит все варианты имеют место быть*.
Reply
#11

Хранить деньги в Float - крайне плохая затея. Как минимум потому, что эти значения могут быть не точными.


Самым разумным вариантом будет хранить все деньги в центах, тогда будет возможность иметь на руках максимум $21474836.47, да и выводить эти числа можно довольно просто:
PHP Code:
stock PrintMoney(value)
{
    
printf("%d.%d"value 100value 100);

Если этого значения не достаточно, то можно воспользоваться библиотекой, которая позволяет работать с переменными, больше, чем 32 бита: https://sampforum.blast.hk/showthread.php?tid=392263


P.S. Если не хочешь париться с выводом значения, как в коде выше, то ты можешь воспользоваться formatex.

Добавить новый спецификатор можно так:
PHP Code:
FormatSpecifier<\'m\'>(output[], money) {
    
format(outputsizeof(output), "%d.%d"money 100money 100);

и использовать так:
PHP Code:
format(stringsizeof(string), "Деньги: %m"money);
SendClientMessage(playerid, -1string); 
Reply
#12

Quote:
Originally Posted by ZiGGi
View Post
Хранить деньги в Float - крайне плохая затея. Как минимум потому, что эти значения могут быть не точными.


Самым разумным вариантом будет хранить все деньги в центах, тогда будет возможность иметь на руках максимум $21474836.47, да и выводить эти числа можно довольно просто:
PHP Code:
stock PrintMoney(value)
{
    
printf("%d.%d"value 100value 100);

Если этого значения не достаточно, то можно воспользоваться библиотекой, которая позволяет работать с переменными, больше, чем 32 бита: https://sampforum.blast.hk/showthread.php?tid=392263


P.S. Если не хочешь париться с выводом значения, как в коде выше, то ты можешь воспользоваться formatex.

Добавить новый спецификатор можно так:
PHP Code:
FormatSpecifier<\'m\'>(output[], money) {
    
format(outputsizeof(output), "%d.%d"money 100money 100);

и использовать так:
PHP Code:
format(stringsizeof(string), "Деньги: %m"money);
SendClientMessage(playerid, -1string); 
Хорошо.

Кажется снова придется переписывать код с Float на Int...
Reply
#13

Решил попробовать с formatex, но проблема в том что в обычном худе отображается вся сумма: http://i.imgur.com/Bh9J6ft.png


Либо я что то не поняли и сделал неправильно изначально.
Reply
#14

Quote:
Originally Posted by Johhnyllll
View Post
Решил попробовать с formatex, но проблема в том что в обычном худе отображается вся сумма: http://i.imgur.com/Bh9J6ft.png


Либо я что то не поняли и сделал неправильно изначально.
У тебя есть два варианта:

1. Замени стандартный худ своим ТД.

2. Перехватывай GivePlayerMoney и дели сумму на 100, а в переменную записывай всё значение.
Reply
#15

Quote:
Originally Posted by ZiGGi
View Post
У тебя есть два варианта:

1. Замени стандартный худ своим ТД.

2. Перехватывай GivePlayerMoney и дели сумму на 100, а в переменную записывай всё значение.
Воспользовался вторым вариантом, теперь всё работает отлично, спасибо.
Reply
#16

PHP Code:
stock Cash_Give(playeridamount)
{
    
P[playerid][p_cash] = P[playerid][p_cash]+amount;
    
GivePlayerMoney(playeridamount);
    
printf("amount %i",amount);
}
CMD:money(playeridparams[]){
    new 
usermoney,cent;
    if(
sscanf(params,"p<.>uiI(0)",user,money,cent)) return SendClientMessage(playerid, -1"Use /money [ID] [cash]");
    
Cash_Give(playeridmoney+cent);
    return 
true;

При попытке дать игроку деньги увеличивается число и в худе и в TD и из-за этого получается сбой между количество денег из БД с тем что игрок видит у себя.

Я не знаю как сделать так что бы всё совпадало с тем что есть в бд.


//update


Сделал так:
PHP Code:
stock Cash_Give(playeridamount)
{
    
P[playerid][p_cash] = P[playerid][p_cash]+amount;
    if(
amount%100 0) {
        
GivePlayerMoney(playeridamount/100);
        
printf("2amount %i.%i",amount/100,amount%100);
    }
    else if(
amount/100 == 0){
        
GivePlayerMoney(playerid, (amount%100)/100);
        
printf("1amount %i.%i",amount/100,amount%100);
    }

Но работает лишь первая часть кода, т.е. 2amount, а если сменить их местами, то будет работать только 1amount.
Reply
#17

Как-то так:
PHP Code:
stock Cash_Give(playeridamount
{
    
P[playerid][p_cash] += amount;
    
ResetPlayerMoney(playerid);
    
GivePlayerMoney(playeridP[playerid][p_cash] / 100); 

Но я бы рекомендовал использовать свой TD денег.
Reply
#18

Quote:
Originally Posted by ZiGGi
View Post
Как-то так:
PHP Code:
stock Cash_Give(playeridamount
{
    
P[playerid][p_cash] += amount;
    
ResetPlayerMoney(playerid);
    
GivePlayerMoney(playeridP[playerid][p_cash] / 100); 

Но я бы рекомендовал использовать свой TD денег.
Спасибо.


Для тех кто столкнётся с подобной проблемой:
PHP Code:
//если не умножать Money на 100, тогда система просто будет считать их за центы
// 1 = 0.1
// 1*100 = 1.0
Cash_Give(playerid, (money*100)+cent); 
Reply
#19

Quote:
Originally Posted by Johhnyllll
View Post
Спасибо.


Для тех кто столкнётся с подобной проблемой:
PHP Code:
//если не умножать Money на 100, тогда система просто будет считать их за центы
// 1 = 0.1
// 1*100 = 1.0
Cash_Give(playerid, (money*100)+cent); 
Бред какой-то, с такой системой тебе нужно все цены записывать в центах, чтобы подобной ерундой не заниматься.

А если уж очень хочется использовать доллары и центы, то хотя бы так:
PHP Code:
stock Cash_Give(playeriddollarscents)  

    
P[playerid][p_cash] += dollars 100 cents
    
ResetPlayerMoney(playerid); 
    
GivePlayerMoney(playeridP[playerid][p_cash] / 100);  

Но так всё-равно делать не нужно.
Reply
#20

Quote:
Originally Posted by ZiGGi
View Post
Но так всё-равно делать не нужно.
Почему?
Reply


Forum Jump:


Users browsing this thread: 6 Guest(s)