Raised This Month: $51 Target: $400
 12% 

Solved Compairing two floats


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-23-2018 , 18:38   Compairing two floats
Reply With Quote #1

Hi,

what is a best practice for compairing two float numbers written as a string?

Let's imagine we have cfg:
Quote:
one_var "10"

second_var "10.000"

// some garbage
third_var "10s"
And now we have:
Code:
char sValue[100];

ConVar cvar = FindConVar("one_var");
cvar.GetString(sValue, sizeof(sValue));
Next, we need to compare sValue with the values stored in cfg.
sValue is "10.0" and in cfg we have "10.000", "10" and "10s"

How to do it reliably without throw some error?

I guess, I need cast both string to float and do equating operation.
But first, I also need to check whether string is a correct float number.

1) If I good understand, sm has no function to do such check? Isn't it?
2) If I do StringToFloat(sVar1) == StringToFloat(sVar2), can do I catch the accuracy error?
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]

Last edited by Dragokas; 05-24-2018 at 09:58.
Dragokas is offline
hmmmmm
Great Tester of Whatever
Join Date: Mar 2017
Location: ...
Old 05-23-2018 , 18:58   Re: Compairing two floats
Reply With Quote #2

For getting the float value from a cvar you should just get it directly as a float rather than as a string then convert. e.g. float value = FindConVar("one_var").FloatValue;

As for comparing floats in general using == is a bad idea since they might be very similar but not exactly the same due to slight floating point errors. You can try using a stock like the following to check if they're almost equal, with some degree of error:

PHP Code:
stock bool AreAlmostEqualfloat afloat bfloat precision 0.001 )
{
    return 
FloatAbs) <= precision;


Last edited by hmmmmm; 05-23-2018 at 19:01.
hmmmmm is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-23-2018 , 19:10   Re: Compairing two floats
Reply With Quote #3

Quote:
Originally Posted by hmmmmm
...you should just get it directly as a float rather than as a string then convert...
I don't know in advance whether Cvar is numeric (float), because I enum all Cvars.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]

Last edited by Dragokas; 05-23-2018 at 19:11.
Dragokas is offline
hmmmmm
Great Tester of Whatever
Join Date: Mar 2017
Location: ...
Old 05-23-2018 , 22:01   Re: Compairing two floats
Reply With Quote #4

Quote:
Originally Posted by Dragokas View Post
I don't know in advance whether Cvar is numeric (float), because I enum all Cvars.
If you can call GetString you can call FloatValue.

EDIT: Nevermind I see what you mean. You can check all the characters in the string and make sure there are no characters that aren't "0-9" or ".", if there are then it isn't a number
Might also be worth checking what FloatValue gives you for non-float values

Last edited by hmmmmm; 05-23-2018 at 22:03.
hmmmmm is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-24-2018 , 06:01   Re: Compairing two floats
Reply With Quote #5

Code:
	PrintToServer("10.0 = %f", StringToFloat("10.0"));
	PrintToServer(".5 = %f", StringToFloat(".5"));
	PrintToServer("1.3e+5 = %f", StringToFloat("1.3e+5"));
	PrintToServer("1.2.3 = %f", StringToFloat("1.2.3"));
	PrintToServer("1s = %f", StringToFloat("1s"));
	PrintToServer("s = %f", StringToFloat("s"));
	PrintToServer("0 = %f", StringToFloat("0"));
	PrintToServer("true = %f", StringToFloat("true"));
	PrintToServer("false = %f", StringToFloat("false"));
	PrintToServer("99999999999999999999999999 = %f", StringToFloat("99999999999999999999999999"));
Quote:
10.0 = 10.000000
.5 = 0.500000
1.3e+5 = 130000.000000
1.2.3 = 1.200000
1s = 1.000000
s = 0.000000
0 = 0.000000
true = 0.000000
false = 0.000000
99999999999999999999999999 = 100000002537764200000000000.000000
hm, all conversions have passed without errors.
However, there is no difference between numeric and string. Both returns 0.000000.
So, manual check, is compulsory.

Thanks for help, hmmmmm.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Neuro Toxin
Veteran Member
Join Date: Oct 2013
Location: { closing the void; }
Old 05-24-2018 , 07:23   Re: Compairing two floats
Reply With Quote #6

Quote:
Originally Posted by hmmmmm View Post
If you can call GetString you can call FloatValue.

EDIT: Nevermind I see what you mean. You can check all the characters in the string and make sure there are no characters that aren't "0-9" or ".", if there are then it isn't a number
Might also be worth checking what FloatValue gives you for non-float values
This is my method to determine a datatype from a string in Dynamic.

Edit: Note: You want to allow char[0] to be - for negative values.
__________________

Last edited by Neuro Toxin; 05-24-2018 at 07:49.
Neuro Toxin is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-24-2018 , 09:06   Re: Compairing two floats
Reply With Quote #7

Thanks.

I think, I'll use such regexp:
Quote:
^(((\+|-)?\d+(\.\d+)?)|((\+|-)?\.\d+))((e|E)(\+|-)\d+)?$
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-24-2018 , 09:56   Re: Compairing two floats
Reply With Quote #8

Looks like working good.

Code:
#include <sourcemod>
#include <regex>

bool IsNumeric(char[] Str)
{
	static Regex regex; static bool bInit;
	if (!bInit) {
		bInit = true;
		regex = new Regex("^(((\\+|-)?\\d+(\\.\\d+)?)|((\\+|-)?\\.\\d+))(e(\\+|-)\\d+)?$", PCRE_CASELESS);
	}
	return (regex.Match(Str) > 0);
}

void TryFloat(char[] Str)
{
	if (IsNumeric(Str)) {
		PrintToServer("%s => %f", Str, StringToFloat(Str));
	} else {
		PrintToServer("%s is not a valid number => %f", Str, StringToFloat(Str));
	}
}

public void OnPluginStart()
{
	TryFloat("0");
	TryFloat(".1");
	TryFloat("+2.0E+2");
	TryFloat("-.555e-3");
	TryFloat("e+1");
	TryFloat("1e");
	TryFloat("aaa");
}
Quote:
0 => 0.000000
.1 => 0.100000
+2.0E+2 => 200.000000
-.555e-3 => -0.000554
e+1 is not a valid number => 0.000000
1e is not a valid number => 1.000000
aaa is not a valid number => 0.000000
Little difference in behaviour for "1e" string, but I think for me it's ok.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]
Dragokas is offline
Neuro Toxin
Veteran Member
Join Date: Oct 2013
Location: { closing the void; }
Old 05-24-2018 , 10:45   Re: Compairing two floats
Reply With Quote #9

Just check if the regex is null rather than throwing in a bool flag.
__________________
Neuro Toxin is offline
Dragokas
Veteran Member
Join Date: Nov 2017
Location: Ukraine on fire
Old 05-24-2018 , 10:56   Re: Compairing two floats
Reply With Quote #10

-------
Ahh, ok, thanks.
__________________
Expert of CMD/VBS/VB6. Malware analyst. L4D fun (Bloody Witch & FreeZone)
[My plugins] [My tools] [GitHub] [Articles] [HiJackThis+] [Donate]

Last edited by Dragokas; 05-24-2018 at 11:01.
Dragokas is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 12:23.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode