# sperating a number by threes

• 01-07-2013
Garrett85
sperating a number by threes
Below is my script, my question is in three comment lines in the function? If you know how I can pull this off please let me know. Thanks.

Code:

```#! /bin/bash # Program to take user input number and return it as a sentence. # Get user input read -p "Enter a number no higher than the billions range" NUM NUMBEROFDIGITS=\${#NUM} ################################### ### FUNCTION-FindNumberOfGroups ### ################################### FindNumberOfGroups() {     if [[ `expr \${NUMBEROFDIGITS} % 3` -eq 0 ]]; then # line is good for determining if there is an odd number of digits when dividing by 3         NUMBEROFGROUPS=\$( expr \${NUMBEROFDIGITS} / 3 )         echo \${NUMBEROFGROUPS}     else         echo "remainder"         NUMBEROFGROUPS=\$( expr \${NUMBEROFDIGITS} / 3 )         let NUMBEROFGROUPS=NUMBEROFGROUPS+1         echo \${NUMBEROFGROUPS}         # here I need to seperate NUMBEROFDIGITS divided by 3 from it's remainder         # if the number is 4500 I need to seperate the number into two groups and add two leading zeros to the left number, e.g. 004 500         # if the number is 61382 I need to seperate the number into two groups and add one leading zero to the left number, e.g. 061 382     fi } #################### ### END FUNCTION ### #################### FindNumberOfGroups```
• 01-07-2013
Irithori
printf has the capability to insert a thousand separator.
Caution: The char depends on LC_LOCALE, so it is not always a dot. (But one can set LC_LOCALE before calling printf)

The idea is:
printf outputs a separated version of a decimal number, which can then be further processed to e.g. replace the dot with a white space.

Now, the requirement of padding the leading group with zeros is a bit evil.
Because one needs to know the length of the printed decimal beforehand, and the dots (if any) also take a place.
Hence the case statement.

Code:

```#!/usr/bin/env bash NUM=12345678901234 let MOD=\${#NUM}%3 let GRPS=\${#NUM}/3 case \$MOD in 1)   let LENGTH=\${#NUM}+2+\$GRPS;; 2)   let LENGTH=\${#NUM}+1+\$GRPS;; *)   let LENGTH=\${#NUM}+\$GRPS-1;; esac # zero padded, dot separated number assigned to a variable a=\$(printf "%'0*d\n" \$LENGTH \$NUM) echo \$a # If there wouldnt be a requirement for leading zeros, it is easier. # No need for \$LENGTH printf "%'d\n" \$NUM```
• 01-07-2013
drl
Hi.

Not tested, thought experiment: perhaps look at reminder (%) of division of length by 3, print that number of leading zeros ("...0*d ...", ... remainder) ... cheers, drl
• 01-07-2013
watael
let's make it look a bit more "bashy"
Code:

```#!/bin/bash number=12345678901234 (( modulo=\${#number}%3 , periods=\${#number}/3 )) (( modulo == 1 ? (length=\${#number}+periods+2) :   modulo == 2 ? (length=\${#number}+periods+1) :                 (length=\${#number}+periods-1) )) printf "%'0*d\n" \$length \$number printf "%'d\n" \$number```
i've been tedious
Code:

```var=\$1 v=\${#var} for ((i=v; i>=0; i--)) do   t=\${var:\$i}   ((\${#t}>=3)) && { var=\${var%\$t*}; ar=( \$t \${ar[@]} ); t="";} done printf -vval '%.3d ' \$t \${ar[@]} echo \$val```
• 01-07-2013
Irithori
Ok, you know bash :)

- The code iterates backwards and number by number over \$var.
- \$t is assigned the part between the current position and the end of \$var
- Once the length of \$t is three, \$t is cut from \$var and also an array is build.
- So after the loop, there is a nice array of 3-digit numbers and (possibly) a one or two digit number in \$t
- the printf assigns \$val with a formated \$t and all elements of \${ar[@]}

I didnt know about the -v VAL option. Thanks.
• 01-08-2013
alf55
Quote:

Originally Posted by Garrett85
Below is my script, my question is in three comment lines in the function? If you know how I can pull this off please let me know. Thanks.

Code:

```#! /bin/bash # Program to take user input number and return it as a sentence. # Get user input read -p "Enter a number no higher than the billions range" NUM NUMBEROFDIGITS=\${#NUM} ################################### ### FUNCTION-FindNumberOfGroups ### ################################### FindNumberOfGroups() {     if [[ `expr \${NUMBEROFDIGITS} % 3` -eq 0 ]]; then # line is good for determining if there is an odd number of digits when dividing by 3         NUMBEROFGROUPS=\$( expr \${NUMBEROFDIGITS} / 3 )         echo \${NUMBEROFGROUPS}     else         echo "remainder"         NUMBEROFGROUPS=\$( expr \${NUMBEROFDIGITS} / 3 )         let NUMBEROFGROUPS=NUMBEROFGROUPS+1         echo \${NUMBEROFGROUPS}         # here I need to seperate NUMBEROFDIGITS divided by 3 from it's remainder         # if the number is 4500 I need to seperate the number into two groups and add two leading zeros to the left number, e.g. 004 500         # if the number is 61382 I need to seperate the number into two groups and add one leading zero to the left number, e.g. 061 382     fi } #################### ### END FUNCTION ### #################### FindNumberOfGroups```

Assuming this is not an assignement, here is an example in "bash" (rather than sh or ksh).
Code:

``` FindNumberOfGroups() {     local index     local padding_string="000"     local num="\${1}"     local len_mod_3=\$((\${#num} % 3))     if [ "\${len_mod_3}" != "0" ] ; then         num="\${padding_string:0:\$((3 - \${len_mod_3}))}\${num}"         len_mod_3=\$((\${#num} % 3))     fi     group_cnt=\$((\${#num} / 3))     #for index in \$(seq 0 3 \${len_of_num}); do     for index in \$(seq 0 3 \${#num}); do       [ \$index -ne 0 ] && printf " "       printf "\${num:\${index}:3}"     done     printf "\n" }```
Which produces an output of:
Code:

```bash\$ FindNumberOfGroups 123456789 123 456 789 bash\$ echo bash\$ FindNumberOfGroups 12345678 012 345 678 bash\$ echo bash\$ FindNumberOfGroups 1234567 001 234 567 bash\$ echo bash\$ FindNumberOfGroups 123 123  bash\$ echo bash\$ FindNumberOfGroups 12 012  bash\$ echo bash\$ FindNumberOfGroups 1 001  bash\$```
• 01-08-2013
watael
you forgot to define `\$len_of_num` to `seq', it should be \${#num}