0

Hi I have a string variable in tcl that stores some integer value. I need to get the left most digit from the string variable and increment it by 1. Basically below is the code that I wrote to accomplish my task :

set maxID 123456;
if {$maxID < 1000000} {
  set maxID 1000000;
} elseif {$maxID >= 1000000} {
  set maxID [expr [string index $maxID 0] + 1]000000; #Need to Simplify this
}
return $maxID;

Now what I am trying to do is if the maxID is greater than or equal to 1 million, set the maxID to the next million value. So in above example since maxID is 123456, the return maxID value should be 1000000 since the next million value for 123456 is 1000000.

So to do that, I am getting the left most digit which is 1, then increment it by 1 and concat six zeros which will increment the value. I am using tcl 8.5.x so I still don't have [string cat $args $args...] command available.

Anyways, I was wondering if there is any simpler way of doing the same.

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Naphstor
  • 2,356
  • 7
  • 35
  • 53

2 Answers2

0

What you're doing seems a buggy way to go about doing that. Much better to make use of the fact that the % operator does integer division when presented with integers.

if {$maxID >= 1000000} {
    set bigbits [expr {$maxID / 1000000}]
    incr bigbits
    set maxID [expr {$bigbits * 1000000}]
    # Converting the three lines above into one is left as an exercise ;-)
} else {
    incr maxID
}

In the simplest case, you might be able to get away with this:

if {$maxID >= 1000000} {
    incr maxID 1000000
} else {
    incr maxID
}

# Or:  incr maxID [expr {$maxID >= 1000000 ? 1000000 : 1}]

but that depends on the input value already being a well-formed member of the sequence; that might be totally a bad idea.

Donal Fellows
  • 133,037
  • 18
  • 149
  • 215
  • You mention the `%` operator but don't use it in your example code... I guess you mean `/` anyway? And also I don't think that `maxID` is supposed to be incremented by 1 if it's less than a million. – mkrieger1 Apr 12 '17 at 09:22
0

Don't use string manipulations to do mathematical operations. It requires a special case for values less than 1000000 and it doesn't work correctly for values above 9999999 (E.g., 10000000 results in 2000000 instead of 11000000).

What you want to do is to round up maxID to the nearest multiple of a million. You can do this in very simple code without requiring special case handling by using mathematical operators. In addition, that allows rounding up to multiples of something else than a million with no extra effort:

proc roundUp {value {step 1000000}} {
    expr {($value / $step + 1) * $step}
}

Here are some examples:

> roundUp 0
1000000
> roundUp 123456
1000000
> roundUp 999999
1000000
> roundUp 1000000
2000000
> roundUp 9999999
10000000
> roundUp 10000000
11000000

Using a different step than 1000000:

> roundUp 5 6
6
> roundUp 6 6
12
mkrieger1
  • 19,194
  • 5
  • 54
  • 65