Is there a way to optimize this code?
#1

Hello guys, I want to devide this string "21.99" into two part, cash: "21" and coin: "99". I do this and it works, but I think it may be slow. Can you help me optimize it?

PHP код:
new _money[11] = "21.99",
        
cash[11],
        
coin[3],
        
_cash,
        
_coin,
        
dot;
    
dot strfind(_money".");
    if(
dot != 1)
    {
        
strmid(cash_money0dot);
        
strmid(coin_moneydot+1dot+3);
        
_cash strval(cash);
        
_coin strval(coin);
        
printf("money: %s, cash: %d, coin: %d"_money_cash_coin);
    } 
Output:
Quote:

money: 21.99, cash: 21, coin: 99

Thanks in advanced.
Reply
#2

Sscanf plugin: https://sampforum.blast.hk/showthread.php?tid=570927
Download: https://github.com/maddinat0r/sscanf/releases

pawn Код:
new _money[] = "21.99", cash, coin;
sscanf(_money, "dd", cash, coin);
printf("money: %s, cash: %d, coin: %d", _money, cash, coin);
Reply
#3

Quote:
Originally Posted by ******
Посмотреть сообщение
Why do you think it is slow? Why are you worried? Have you profiled your mode and found this to be a bottleneck?
I write the code just to see if it works. But it seems long because i create a lot of variables (i don't know if creating a lot of variables like above is needed?) and there're too much steps (strfind, strmid and strval) just to split one short string.

Quote:
Originally Posted by Calisthenics
Посмотреть сообщение
Sscanf plugin: https://sampforum.blast.hk/showthread.php?tid=570927
Download: https://github.com/maddinat0r/sscanf/releases

pawn Код:
new _money[] = "21.99", cash, coin;
sscanf(_money, "dd", cash, coin);
printf("money: %s, cash: %d, coin: %d", _money, cash, coin);
Thank you, this looks shorter (and less variables and may be faster?) than mine.
Reply
#4

Quote:
Originally Posted by DuyDang2412
Посмотреть сообщение
Thank you, this looks shorter (and less variables and may be faster?) than mine.
Well, the plugin is quite fast for splitting data from a string.

However, I did a mistake myself. The code I provided will take space as default delimiter. To set the delimiter, use "p<delimiter_here>rest_here". In your case:
pawn Код:
sscanf(_money, "p<.>dd", cash, coin);
Reply
#5

A silly question, but why are you storing a float in a string to begin with?
String manipulations are always slower than processing the same value in a float or integer.
Reply
#6

Quote:
Originally Posted by Calisthenics
Посмотреть сообщение
Well, the plugin is quite fast for splitting data from a string.

However, I did a mistake myself. The code I provided will take space as default delimiter. To set the delimiter, use "p<delimiter_here>rest_here". In your case:
pawn Код:
sscanf(_money, "p<.>dd", cash, coin);
Thank you, I haven't known about this. It works right now!

Quote:
Originally Posted by AmigaBlizzard
Посмотреть сообщение
A silly question, but why are you storing a float in a string to begin with?
String manipulations are always slower than processing the same value in a float or integer.
Because you cannot split it if it's not a string.
I want to make a function which is similar to GivePlayerMoney(playerid, money); but in this case, I want 'money' as a float. Like I said, I will convert Float:money to string with format %f and then split it. The number before the dot is the cash and the rest is the coin (like 0.99$, 1.99$).
Reply
#7

AmigaBlizzard has got a point. Instead of saving money as string, you can have 2 integer arrays. One being for money and the other for coins. Showing the money would look like this (an example):
pawn Код:
format(string, sizeof string, "My money: %d.%02d$", gPlayer[playerid][Money], gPlayer[playerid][Coins]);
The need of splitting is now unnecessary.

%02d ads zero in front in case it is 1 digit. "9" becomes "09".
Reply
#8

Quote:
Originally Posted by Calisthenics
Посмотреть сообщение
AmigaBlizzard has got a point. Instead of saving money as string, you can have 2 integer arrays. One being for money and the other for coins. Showing the money would look like this (an example):
pawn Код:
format(string, sizeof string, "My money: %d.%02d$", gPlayer[playerid][Money], gPlayer[playerid][Coins]);
The need of splitting is now unnecessary.

%02d ads zero in front in case it is 1 digit. "9" becomes "09".
Actually, I also have those 2 integer arrays just like what you said. It seems that I should write another function like this:
Quote:

_givePlayerMoney(playerid, cash, coin) // I think this will be the best

not
Quote:

_givePlayerMoney(playerid, Float:cash)

Thank you!

Quote:
Originally Posted by ******
Посмотреть сообщение
floatround
floatfract

Don't use strings to process numbers.
Sorry but I don't understand much. I haven't found out the way to work with those two functions.
And this is how I use string to do my thing:
PHP код:
_givePlayerMoney(playeridFloat:amount)
{
    new 
_money[18],
        
_cash,
        
_coin;
    
format(_moneysizeof(_money), "%.2f"amount);
    
sscanf(_money"p<.>dd"_cash_coin);
    
ResetPlayerMoney(playerid);
    
character[playerid][cash] += _cash;
    
character[playerid][coin] += _coin;
    
SetPlayerMoney(playeridcharacter[playerid][cash]);
    
updatePlayerCoinTextDraw(playerid); // I create a textdraw to display player's coin
    
return 1;

Reply
#9

He is trying to say don't use strings at all, Use implemented functions to extract the integer and fraction, This "probably, I'm not sure" should be faster than using a string

Explained as much as I can below
PHP код:
_givePlayerMoney(playeridFloat:amount)
{
    
ResetPlayerMoney(playerid);
    
character[playerid][cash] += floatround(amountfloatround_floor);                    //Gets the integer part of a float(Rounds downwards, Ignoring fractions basically)
    
character[playerid][coin] += floatround(floatfract(amount)*100floatround_floor);    //Gets the fraction part of the float, multiply it by a hundred to get the first two fractions (You will have to change that if you use more or less than two fractions, or adjust the code) then use the method above to convert it to an integer
    
    
SetPlayerMoney(playeridcharacter[playerid][cash]);
    
updatePlayerCoinTextDraw(playerid);
    return 
1;

Quote:
Originally Posted by DuyDang2412
Посмотреть сообщение
I write the code just to see if it works. But it seems long because i create a lot of variables (i don't know if creating a lot of variables like above is needed?) and there're too much steps (strfind, strmid and strval) just to split one short string.


Thank you, this looks shorter (and less variables and may be faster?) than mine.
Having variables is fine, as long as you're using them right, Variables don't take much space or time to make anyways, And sometimes they helps clear things out even if they're unnecessary.

an example for the above code with variables:
PHP код:
_givePlayerMoney(playeridFloat:amount)
{
    
ResetPlayerMoney(playerid);
    new 
cash floatround(amountfloatround_floor);
    new 
coin floatround(floatfract(amount)*100floatround_floor);
    
character[playerid][cash] += cash;
    
character[playerid][coin] += coin;
    
SetPlayerMoney(playeridcharacter[playerid][cash]);
    
updatePlayerCoinTextDraw(playerid);
    return 
1;

Reply
#10

Quote:
Originally Posted by xVIP3Rx
Посмотреть сообщение
He is trying to say don't use strings at all, Use implemented functions to extract the integer and fraction, This "probably, I'm not sure" should be faster than using a string

Explained as much as I can below
PHP код:
_givePlayerMoney(playeridFloat:amount)
{
    
ResetPlayerMoney(playerid);
    
character[playerid][cash] += floatround(amountfloatround_floor);                    //Gets the integer part of a float(Rounds downwards, Ignoring fractions basically)
    
character[playerid][coin] += floatround(floatfract(amount)*100floatround_floor);    //Gets the fraction part of the float, multiply it by a hundred to get the first two fractions (You will have to change that if you use more or less than two fractions, or adjust the code) then use the method above to convert it to an integer
    
    
SetPlayerMoney(playeridcharacter[playerid][cash]);
    
updatePlayerCoinTextDraw(playerid);
    return 
1;


Having variables is fine, as long as you're using them right, Variables don't take much space or time to make anyways, And sometimes they helps clear things out even if they're unnecessary.

an example for the above code with variables:
PHP код:
_givePlayerMoney(playeridFloat:amount)
{
    
ResetPlayerMoney(playerid);
    new 
cash floatround(amountfloatround_floor);
    new 
coin floatround(floatfract(amount)*100floatround_floor);
    
character[playerid][cash] += cash;
    
character[playerid][coin] += coin;
    
SetPlayerMoney(playeridcharacter[playerid][cash]);
    
updatePlayerCoinTextDraw(playerid);
    return 
1;

I understood. You really help me out! Thank you.

Quote:
Originally Posted by AmigaBlizzard
Посмотреть сообщение
You don't have to use 2 separate arrays to store this.
When you give the player some money like $450, give him 450 * 100 = 45000.
Then you'll be storing his money in cents instead of whole dollars.

To extract both values (the dollars and cents), you can use it like this:
Код:
	new money, dollars, cents;
	money = 5062; // This is in fact 50 dollars and 62 cents
	dollars = money / 100;
	cents = money - (dollars * 100);

	printf("Money: %i", money);
	printf("Dollars: %i", dollars);
	printf("Cents: %i", cents);
Due to how integers work, dividing the total money in cents by 100, it rounds the result down automatically.
In this example, the dollars variable will hold "50" (5062 / 100 is essentially 50.62 but with integers, the part behind the comma drops away, leaving you with just the value "50").
Then you take the difference between the whole amount of cents and the rounded down value of dollars multiplied by 100.
This will become 5062 - (50 * 100) = 5062 - 5000 = 62.
So with only 1 value, you can store both values and separate them easily.

The only drawback to this: you are only able to store money up to 21 million dollars instead of 2.1 billion dollars due to having a signed 32-bit integer value and using the last 2 digits to store your cents instead of whole dollars.
I would follow your way if I could but a player can have more than 99 cents so your way may not work in some cases. Thanks anyway!
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)