0

I am testing something with a batch file to compare 2 numbers if greater, less or equal. I start making this test to find out why my other script that requires a comparison between 2 numbers and did not work properly. During the test I found the issue and I cannot understand why it's happening. I hope you can help me with this one.

Let's say I have 2 variables:

set a=12.5
set b=10.0

if I compare those 2 numbers:

IF %A% GTR %B% (echo A greater than B) ELSE (IF %A% LSS %B% (echo B greater than A) ELSE (echo A equal B))

The output is: A greater than B

I tested multiple numbers with decimals and works just fine, EXCEPT when one number is less than 10 and the other number is higher than 10.

example:

set a=9.9
set b=12.3

IF %A% GTR %B% (echo A greater than B) ELSE (IF %A% LSS %B% (echo B greater than A) ELSE (echo A equal B))

in this case the output is: A greater than B which is wrong.

Anyone can explain me why is this happening and how to fix this?

phuclv
  • 37,963
  • 15
  • 156
  • 475
JaJe
  • 3
  • 4
  • 3
    `Set /A` performs decimal integer arithmetic, not floating point math. It is therefore not capable of doing what you intend, without modifying your numbers in such a way as to make them whole. _(For example, remove the decimal points, multiply each of by 10, perform your math function(s), and divide the result by 10 again)_ My best advice is to use an alternative scripting language instead of batch files, _(or at least use them from within your batch file)_. As a side note, for consistency, choose your variable name case, then use it throughout, if nothing else, it'll help others to read it. – Compo Jan 13 '20 at 23:14
  • the simplest way is to switch to PowerShell which is far more powerful and does support floating-point types – phuclv Jan 14 '20 at 10:14
  • Thank you very much for your reply guys. I understand that CMD do not support floating points but how comes that comparision between 2 numbers with decimals still works except if one is greater than 10 and the other less than 10 instead of not working at all? – JaJe Jan 14 '20 at 14:16
  • because `.`is not a digit (number), `If` recognizes `%a%` and `%v%`as STRINGs and therefore does a String comparison (character by character). As `9` (the first char of `%a%`) is bigger than `1` (the first char of `%v%`) (to be more precise: the ASCII-code of the character `9` is higher than the ASCII-code of the character `1`) you get those results. – Stephan Jan 14 '20 at 16:56

2 Answers2

1

Run if /? and you'll see that

These comparisons are generic, in that if both string1 and string2 are both comprised of all numeric digits, then the strings are converted to numbers and a numeric comparison is performed.

Since decimal numbers like 12.5, 10.0, 9.9... are not comprised of all numeric digits (they contain the . character), they'll be left as strings and will be compared lexicographically just like the default string comparison in any languages. Since 9 is larger than 1, "9.9" is sorted after "10.0"

In fact just compare any numbers whose number of digits differ and you'll see the same phenomenon. For example 123.5 will be "smaller" than 34.2

To compare numbers lexicographic order they need to have the same width, which means you must pad zeros before and after the numbers so that the lengths before and after the radix point are the same, for example "112.400" and "009.987"

For more information read

phuclv
  • 37,963
  • 15
  • 156
  • 475
  • Wow! This is extremelly informative and interesting. Thank you very much for those links, now everything have much more sense. – JaJe Jan 14 '20 at 18:17
0

phuclv explained it greatly above.

For those who are looking for a solution, you can do 3 things in a batch script to compare numbers with decimal parts:

  1. Use PowerShell to calculate: See this to know how to use powershell in batch file
  2. Use 3rd party .exe file that will compare given numbers in command line arguments. Something like this calc.exe, but I am not sure if it supports the comparison operator!? Anyways, you can just create your own in simple c language and compile it to .exe file.
  3. I have created this function that you can use in batch script:

Following will return -1: decimalCompare.bat 1.215 51.2151

Following will return -1: decimalCompare.bat 00001.215 51.2151

Following will return 0: decimalCompare.bat 54.1246 54.1246

Following will return 1: decimalCompare.bat 112.400 009.987

Following will return -1: decimalCompare.bat 112 229.987

Zaif Senpai
  • 71
  • 3
  • 11