Jump to content

Scale factor (computer science)

From Wikipedia, the free encyclopedia
This is an old revision of this page, as edited by Bmearns (talk | contribs) at 17:41, 2 March 2006. The present address (URL) is a permanent link to this revision, which may differ significantly from the current revision.
(diff) ← Previous revision | Latest revision (diff) | Newer revision → (diff)

A scale factor is used in computer science when a real world set of numbers needs to represented on a different scale in order to fit a specific number format. For instance, a 16 bit unsigned integer (uint16) can only hold a value as large as 65,53510. If unint16's are to be used to represent values from 0 to 131,07010, then a scale factor of 1/2 would be introduced. Notice that while the scale factor extends the range, it also decreases the precision. In this example, for instance, the number 3 could not be represented because a stored 1 represents a real world 2, and a stored 2 represents a real world 4.

Uses

Certain number formats may be chosen for an application for convenience in programming, or because of certain advantages offered by the hardware for that number format . For instance, early proccessors did not natively support the IEEE floating point standard for representing fractional values, so integers were used to store representations of the real world values by applying a scale factor to the real value. By neccessity, this was done in software, since the hardware did not support fractional values.

Operations on Scaled Values

Once the scaled representation of a real value is stored, the scaling can often be ignored until the value needs to come back into the "real world". For instance, adding two scaled values is just as valid as unscaling the values, adding the real values, and then scaling the result, and the former is much easier and faster. For other operations, however, the scaling is very important.

Multiplication, for instance, needs to take account of the fact that both numbers are scaled. As an example, consider two real world values A and B. The real world multiplication of these real world values is:

A * B = P

Now suppose we're storing the values with a scale factor of Z. If we simply multiply the stored representations we'll get the following:

AZ * BZ = Q

Note how AZ is the scaled real world value or A or simply the product of A * Z, and likewise, BZ is the scaled representation of B. Also note that we didn't write PZ as the answer, the reason is simple: PZ is not the answer. You can see this by rearranging the statement, where each line in the following are equivalent:

AZ * BZ = Q
A * Z * B * Z = Q
(A * B) * Z * Z = Q
P * Z * Z = Q
PZ * Z = Q

Note how we substituted P for A * B on line 4. You can now see that the result of AZ * BZ (which is Q) is NOT PZ, it's PZ * Z. If PZ were the answer, we could simply store it directly, since it has the scale factor built in, as is the case with addition and substraction. For multiplication, however, you can see that the product of two scaled values has an extra scaling built in. As long as this is taken into account, there's still no need to convert AZ and BZ into A and B before performing the operation, you just need to divide the result by Z before storing it back. You will then have PZ stored as the result of the multiplication, which is fine because you weren't storing the result of AZ * BZ, you were storing the scaled representatation of the result of A * B.

Common Scaling Scenarios

Fractional Values Scaled to Integers

As already mentioned, many older proccessors (and possibly some current ones) do not natively support fractional mathematics. In this case, fractional values can be scaled into integers by multiplying them by ten to the power of whatever decimal precision you want to retain. In otherwords, if you want to preserve n digits to the right of the decimal point, you need to multiply the entire number by 10n. (Or if you're working in binary and you want to save m digits to the right of the binary point, then you would multiply the number by 2m, or alternately, bit shift the value m places to the right). For example, consider the following set of real world fractional values:

15.400, 0.133, 4.650, 1.000, 8.001

Notice how they all have 3 digits to the right of the decimal place. If we want to save all of that information (in otherwords, not loose any precision), we need to multiply these numbers by 103, or 1,000, giving us integer values of:

15400, 133, 4650, 1000, 8001

(also note that these numbers cannot be stored in 8bit integers, it will require at least 14 bits, or, more realistically, 16.)

Integer values to Fractional

Certain proccessors, particularly DSPs common in the Embedded technology industry, have built in support for the fixed point arithematic, such as Q and IQ formats.

These operations assume that the binary point in a number is always between two specific bits in the field. For instance, in the Q15 format, it is assumed that there are 15 bits to the right of the binary point. This assumption is important when performing fixed point operations which are likely produce values with more bits than either of the operands (for instance, multiplication, where the product could potentially have as many bits as the sum of the number of bits in the two operands). In this case, the answer will likely be rounded or truncated to fit into the same number of bits as the operands. The choice of which bits to pick usually depends on the position of the binary point.


As an example, assume we are using an unsigned 8 bit fixed point format with 4 fractional bits, and 4 integer bits. As mentioned, the highest integer value it can store is 15, and the highest mixed value it can store is 15.9375 (0xFF.FF or 1111.1111b). If the real world values we want to manipulate are in the range [0,160], we need to scale these values in order to get them into fixed point. Note that we can not use a scale factor of 1/10 here because scaling 160 by 1/10 gives us 16, which is greater than the greatest value we can store in our fixed point format. 1/11 will work as a scale factor, however, because 160/11 = 14.5454... which fits in our range. Let's use this scale factor to convert the following real world values into scaled representations:

154, 101, 54, 3, 0, 160

Scaling these with the scale factor (1/11) gives us the following values:

154/11 = 14
101/11 = 9.1818...
54/11 = 4.9090...
3/11 = 0.2727...
0/11 = 0
160/11 = 14.5454...

Note however, that many of these values have been truncated because they contain repeating fractions. When we try to store these in our fixed point format, we're going to loose some of our precision (which didn't seem all that precise when they were just integers). This is an interesting problem because we said we could fit 256 different values into our 8 bit format, and we're only trying to store values from a range with 161 possible values (0 through 160). As it turns out, the problem was our scale factor, 11, which introduced unneccessary precision requirements. The resolution of the problem is to find a better scaling factor. For more information, read on.