Both integer division and integer multiplication work exactly only as long as the result fits within the confines of the type. If it doesn't you get all sorts of truncation etc.
Let's get a simpler version, a char variable [0-255]
unsigned char a = 12;
unsigned char b = a/4;
Since 12/4 = 3 exactly, and 3 is an integer in range between 0 and 255, b is 3. Multiply that by 4, and you get your 12 back.
unsigned char a = 11;
unsigned char b = a/2;
11/2 is 5.5 but integers can't store the fractional part. In this case b is 5 and the 0.5 part is irrecoverably lost. Multiply the b by 2 and you get 10, not 11.
Note, it's truncation, not rounding.
unsigned char a = 100;
unsigned char b = a/15;
100/15 is 6.66(6) - which rounded to nearest integer would be closer to 7. Thing is, we're truncating, not rounding, so (int) 6.6666666666 is 6. The fractional part is forever lost. Now multiply b*15 and you get 90. It's rather far off - it's the cost of using integers instead of floats.
Even worse things happen in overflow.
unsigned char a = 150;
unsigned char b = a*2; //300 with top bit truncated becomes 44
unsigned char c = b/2; // 44/2 = 22
but that's a subject for a different question.
(10/3)*3not equal 10? Hmmm....