Author Topic: Strings As Numbers Comparisons (> or < or particularly <=)  (Read 3823 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Strings As Numbers Comparisons (> or < or particularly <=)
« on: August 16, 2020, 01:38:41 pm »
Seems to me I got burned once or twice treating comparing a number in String form like a regular Type number like INTEGER or LONG, maybe it was in SmallBASIC or Just Basic (yeah, I know that one is screwed up).

But is it safe with QB64?

So far everything looks OK:
Code: QB64: [Select]
  1. _TITLE "String compare test" 'B+ 2020-08-16 seems to be I remember an unexpected result when comparing strings
  2. IF "11111" > "1111" THEN PRINT "11111 > 1111" ELSE PRINT "11111 is NOT > 1111" 'OK it's longer
  3. IF "11111" < "1111" THEN PRINT "11111 < 1111" ELSE PRINT "11111 is NOT < 1111" 'OK it's longer
  4. IF "110" > "111" THEN PRINT "110 > 111" ELSE PRINT "110 is NOT > 111"
  5. IF "110" < "111" THEN PRINT "110 < 111" ELSE PRINT "110 is NOT < 111"
  6. IF "112" > "111" THEN PRINT "112 > 111" ELSE PRINT "112 is NOT > 111"
  7. IF "112" < "111" THEN PRINT "112 < 111" ELSE PRINT "112 is NOT < 111"
  8. ' oh I know maybe
  9. IF "110" > "011" THEN PRINT "110 > 011" ELSE PRINT "110 is NOT > 011"
  10. IF "110" < "011" THEN PRINT "110 < 011" ELSE PRINT "110 is NOT < 011"
  11. IF "112" > "011" THEN PRINT "112 > 011" ELSE PRINT "112 is NOT > 011"
  12. IF "112" < "011" THEN PRINT "112 < 011" ELSE PRINT "112 is NOT < 011"
  13. ' no that's OK too
  14. IF "9" > "001" THEN PRINT "9 > 001" ELSE PRINT "9 NOT > 001"
  15. IF "9" < "001" THEN PRINT "9 < 001" ELSE PRINT "9 NOT < 001"
  16. IF "10" > "009" THEN PRINT "10 > 009" ELSE PRINT "10 NOT > 009"
  17. IF "10" < "009" THEN PRINT "10 < 009" ELSE PRINT "10 NOT < 009"
  18.  
  19.  
  20.  

Is there any case where I can't compare a string like an number?

If it is safe, I can eliminate some non needed code in my subtr$ function for String Math and save myself having to make a LessThanOrEqual compare Function for Division.

PS Talking about just digits, no minus sign or decimal or E for Exponents.
« Last Edit: August 16, 2020, 01:41:04 pm by bplus »

FellippeHeitor

  • Guest
Re: Strings As Numbers Comparisons (> or < or particularly <=)
« Reply #1 on: August 16, 2020, 01:43:01 pm »
I'm not sure, but it could be comparing the ascii codes.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Strings As Numbers Comparisons (> or < or particularly <=)
« Reply #2 on: August 16, 2020, 02:16:29 pm »
Yes checking ascii is good!
Code: QB64: [Select]
  1. PRINT "check ascii"
  2. PRINT ASC("0")
  3. PRINT ASC("1")
  4. PRINT ASC("9")
  5.  

Just before checking back here, I had the idea my check in subtr$ may be wrong as it compares lengths of string and assumes the longer is the greater which is fine if all leading 0's were converted to space and trimmed off.

QB64 doing great!
Code: QB64: [Select]
  1. a$ = "00005"
  2. b$ = "50"
  3. PRINT a$ < b$
  4. PRINT a$ <= b$
  5. PRINT a$ >= b$
  6. PRINT a$ > b$
  7.  

This is better than my check in subtr$ that would pick a$ as greater because longer.
« Last Edit: August 16, 2020, 02:18:11 pm by bplus »

FellippeHeitor

  • Guest
Re: Strings As Numbers Comparisons (> or < or particularly <=)
« Reply #3 on: August 16, 2020, 02:28:29 pm »
This is what is going on with string comparison behind the scenes:

Code: C++: [Select]
  1. int32 qbs_equal(qbs *str1,qbs *str2){
  2.     if (str1->len!=str2->len) return 0;
  3.     if (memcmp(str1->chr,str2->chr,str1->len)==0) return -1;
  4.     return 0;
  5. }
  6. int32 qbs_notequal(qbs *str1,qbs *str2){
  7.     if (str1->len!=str2->len) return -1;
  8.     if (memcmp(str1->chr,str2->chr,str1->len)==0) return 0;
  9.     return -1;
  10. }
  11. int32 qbs_greaterthan(qbs *str2,qbs *str1){
  12.     //same process as for lessthan; we just reverse the string order
  13.     int32 i, limit, l1, l2;
  14.     l1 = str1->len; l2 = str2->len;  
  15.     if (!l1) if (l2) return -1; else return 0;
  16.     if (l1<=l2) limit = l1; else limit = l2;
  17.     i=memcmp(str1->chr,str2->chr,limit);
  18.     if (i<0) return -1;
  19.     if (i>0) return 0;
  20.     if (l1<l2) return -1;  
  21.     return 0;
  22. }
  23. int32 qbs_lessthan(qbs *str1,qbs *str2){
  24.     int32 i, limit, l1, l2;
  25.     l1 = str1->len; l2 = str2->len;  //no need to get the length of these strings multiple times.
  26.     if (!l1) if (l2) return -1; else return 0;  //if one is a null string we known the answer already.
  27.     if (l1<=l2) limit = l1; else limit = l2; //our limit is going to be the length of the smallest string.
  28.     i=memcmp(str1->chr,str2->chr,limit); //check only to the length of the shortest string
  29.     if (i<0) return -1; //if the number is smaller by this point, say so
  30.     if (i>0) return 0; // if it's larger by this point, say so
  31.     //if the number is the same at this point, compare length.
  32.     //if the length of the first one is smaller, then the string is smaller. Otherwise the second one is the same string, or longer.
  33.     if (l1<l2) return -1;  
  34.     return 0;
  35. }
  36. int32 qbs_lessorequal(qbs *str1,qbs *str2){
  37.     //same process as lessthan, but we check to see if the lengths are equal here also.
  38.     int32 i, limit, l1, l2;
  39.     l1 = str1->len; l2 = str2->len;
  40.     if (!l1) return -1;  //if the first string has no length then it HAS to be smaller or equal to the second
  41.     if (l1<=l2) limit = l1; else limit = l2;
  42.     i=memcmp(str1->chr,str2->chr,limit);
  43.     if (i<0) return -1;
  44.     if (i>0) return 0;
  45.     if (l1<=l2) return -1;  
  46.     return 0;
  47. }
  48. int32 qbs_greaterorequal(qbs *str2,qbs *str1){
  49.     //same process as for lessorequal; we just reverse the string order
  50.     int32 i, limit, l1, l2;
  51.     l1 = str1->len; l2 = str2->len;
  52.     if (!l1) return -1;
  53.     if (l1<=l2) limit = l1; else limit = l2;
  54.     i=memcmp(str1->chr,str2->chr,limit);
  55.     if (i<0) return -1;
  56.     if (i>0) return 0;
  57.     if (l1<=l2) return -1;  
  58.     return 0;
  59. }

The results you're getting are the results of the memcmp function in C++.

http://www.cplusplus.com/reference/cstring/memcmp/

This is better than my check in subtr$ that would pick a$ as greater because longer.

Beware that length is being compared here too.
« Last Edit: August 16, 2020, 02:30:35 pm by FellippeHeitor »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Strings As Numbers Comparisons (> or < or particularly <=)
« Reply #4 on: August 16, 2020, 02:50:47 pm »
Yes, I have come to conclusion I have to roll my own specially for what I have sketched for division.

Thanks for lookup @FellippeHeitor

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Strings As Numbers Comparisons (> or < or particularly <=)
« Reply #5 on: August 16, 2020, 03:11:10 pm »
Here's where QB64 fails (my needs):
Code: QB64: [Select]
  1. PRINT "Here's the problem:"
  2. a$ = "1" + STRING$(99, "0")
  3. b$ = STRING$(99, "9")
  4. PRINT " True: "; a$ > b$ 'true
  5. PRINT "False: "; a$ < b$ 'false
  6.  
« Last Edit: August 16, 2020, 03:13:15 pm by bplus »