# Thread: sperating a number by threes

Enjoy an ad free experience by logging in. Not a member yet? Register.
1. ## 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```

2. 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```

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

4. \$spacer_open \$spacer_close
5. 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```

6. 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.

7. 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 num="\${1}"
local len_mod_3=\$((\${#num} % 3))
if [ "\${len_mod_3}" != "0" ] ; then
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\$```

8. you forgot to define `\$len_of_num` to `seq', it should be \${#num}

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•