0

I'm trying to check whether the input string contains all digits or not. I achieved this using 2 different algos. One is to convert the string to integer using String.toInt() and then checking if its value lies between the integer of length of the input string.

e.g. If input string is "123". The corresponding integer must lie between 100-999.

Second, I wrote a function that iterates over each character of the string and checks if its ASCII values lies between 48-57. If not, it returns false.

When I bench marked these two algos, I found that when the string contains only digits, the 2nd algo is about 9 times faster than the 1st one. But when the string contains even a single non-digit character, the 1st algo takes ~1ms, but the 2nd algo always takes ~5ms. Why is this? I've not been able to figure this out.

The code:

unsigned long start;
unsigned long middle;
unsigned long end;

void setup() {
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }

  // send an intro:
  Serial.println("String toInt():");
  Serial.println();
}

void loop() {
  // Read serial input:
  if (Serial.available()) {
    String r = Serial.readString();

    start = micros();
    unsigned long rInt = r.toInt();
    int rLen = r.length();

    if ((rInt >= floor(pow(10, rLen))) || (rInt < floor(pow(10, rLen-1)))) {
      Serial.println("Please enter valid integer value!");
    } else {
      Serial.println(rInt+1);
    }

    middle = micros();

    bool isInt = doesContainInteger(r);
    if (isInt) {
      Serial.println(r);
    } else {
      Serial.println("Please enter valid integer value!");
    }

    end = micros();

    Serial.println(middle-start);
    Serial.println(end-middle);
  }
}

bool doesContainInteger(String s)
{
  int sLen = s.length();
  for (int i=0; i<sLen; i++) {
    char sChar = s.charAt(i);
    if (sChar<48 || sChar>57) {
      return false;
    }
  }
  return true;
}
5
  • 1
    Instead of "Please enter valid integer value!", just print "Invalid int". You will get somewhat less unrealistic timings. Commented Apr 2, 2017 at 11:21
  • You were right! I replaced "Please enter valid integer value!" with "!", and it took just 80us to print. Commented Apr 2, 2017 at 11:51
  • Including the serial output in your calculation timing is just plain stupid. Your timing should start before your test routine and finish immediately afterwards.
    – Majenko
    Commented Apr 2, 2017 at 12:30
  • 1
    Oh, and pow() is a horrendously slow routine. Avoid it at all costs.
    – Majenko
    Commented Apr 2, 2017 at 12:31
  • @Majenko Thanks. Your feedback is always valuable! Commented Apr 2, 2017 at 16:17

2 Answers 2

-1

1 ms means easy calculation.

2 ms means more time spent in calculation.

5 ms means far more time in message printing to Serial buffer.

I calculated the error message passes serial line in 20-30 msec, so that is why I think there has to be a little bit faster buffer in between there.

1

As pointed out by Majenko in his (slightly annoyed) comment, you need to change your timing code to time only the calculations you want benchmark, not the I/O or other irrelevant code. For checking the conversion using toInt(), for example, try:

// time our conversion
unsigned long start = micros();
unsigned long rInt = r.toInt();
bool invalid = rInt == 0;
unsigned long end = micros();

// print the result
if (invalid) {
    Serial.print("in");
}
Serial.print("valid conversion took ");
Serial.print(end - start);
Serial.print(" microseconds.");

Note that your assumption that a three-character input that's a valid integer will be between 100 and 999 is wrong; "003" and "-17" are both three-character inputs that should be correctly converted.

According to the toInt() documentation, 0 is returned on failure to convert, so I check for that in the code above. But since one can't tell the difference between a successful conversion of "0" and unsuccessful conversion of "abc" or some other non-integer, you really should be sure before you call toInt() that you've got a valid integer int the string.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.