Computer problem

JohnM16

New member
Joined
Jan 7, 2019
Messages
2
Hi Folks,


the computer system I work on (as a programmer) deals, among other things, with material quantity conversions.


So, in a stock control context, a certain mass of a material may be stored as a value in kilograms. However, an operator may request the same value expressed in pounds, which is not stored directly.


To automatically make the conversion, the system stores a numerator and a denominator for each unit, and these are used where required to give the output in alternative units.


Easier if I give an example:


Material 'red paint' has a current stock of 5.00kg. The conversion factors are stored as follows:


Unit Numerator Denominator
KG 1 1
LB 71701 32523


If I request the stock to display in kilograms, the system will calculate the result as (5.00 * 1 / 1) = 5.00 kg

If I request it in pounds, the system will calculate the result as (5.00 * 71701 / 32523) = 11.023 lb.

Those of you familiar with Imperial/SI units will probably have spotted that 71701/32523 is 2.20462, the 'standard' conversion factor from kilos to pounds.


So what's the problem? It's this:


The computer system can only store the numerator/denominator values as integers, each with a maximum of 5 digits. Don't ask, I didn't design it, and it isn't something that can be changed.


Therefore, all the stored conversion factors have to be the quotient of a divisor and dividend that are both held as integers.


For new data, this is harder than it sounds. If someone gave you the value 2.20462 and asked you to express it as the quotient of two unknown integers (max 5 digits each), you might have to scratch your head. Especially if the target value could be the result of more than one division calculation.


I could write a program to figure this out for any quotient (and I'm sure you could too), but it would be inefficient and rely on number crunching. What I'm after is a more elegant and efficient way of arriving at the desired result.


Example 2: I need a conversion factor from kg/m2 (kilograms per square metre) to ft2/lb (square feet per pound). The required conversion factor, expressed as a decimal, is 0.2048146. BTW, these units are real, and are applied in the context of mass coverage (think of paint).


Because of the 5 digit restriction, the value resulting from the calculation may not be exact; but we do need it to be as accurate as possible. If I programmed it, in my inefficient, number-crunching way, the logic would have to be recursive, so as to get nearer to my 'perfect result' until the possibilities were exhausted.


But there may be a better way, which is why I've posted this.


To sum up (per example 2 above), a/b = 0.2048146, where a and b are positive integers, max 5 digits each. How close is it possible to get with a single division calculation? Can we get closer using 2 calculations with 4 unknowns e.g.: a/b * c/d = 0.2048146 ?


Thank you for reading and (I hope) understanding.


Best regards,


A non-mathematician.
 
Hi Folks,

the computer system I work on (as a programmer) deals, among other things, with material quantity conversions.

So, in a stock control context, a certain mass of a material may be stored as a value in kilograms. However, an operator may request the same value expressed in pounds, which is not stored directly.

To automatically make the conversion, the system stores a numerator and a denominator for each unit, and these are used where required to give the output in alternative units.

Easier if I give an example:

Material 'red paint' has a current stock of 5.00kg. The conversion factors are stored as follows:

Unit Numerator Denominator
KG 1 1
LB 71701 32523

If I request the stock to display in kilograms, the system will calculate the result as (5.00 * 1 / 1) = 5.00 kg

If I request it in pounds, the system will calculate the result as (5.00 * 71701 / 32523) = 11.023 lb.

Those of you familiar with Imperial/SI units will probably have spotted that 71701/32523 is 2.20462, the 'standard' conversion factor from kilos to pounds.

So what's the problem? It's this:

The computer system can only store the numerator/denominator values as integers, each with a maximum of 5 digits. Don't ask, I didn't design it, and it isn't something that can be changed.

Therefore, all the stored conversion factors have to be the quotient of a divisor and dividend that are both held as integers.

For new data, this is harder than it sounds. If someone gave you the value 2.20462 and asked you to express it as the quotient of two unknown integers (max 5 digits each), you might have to scratch your head. Especially if the target value could be the result of more than one division calculation.

I could write a program to figure this out for any quotient (and I'm sure you could too), but it would be inefficient and rely on number crunching. What I'm after is a more elegant and efficient way of arriving at the desired result.

Example 2: I need a conversion factor from kg/m2 (kilograms per square metre) to ft2/lb (square feet per pound). The required conversion factor, expressed as a decimal, is 0.2048146. BTW, these units are real, and are applied in the context of mass coverage (think of paint).

Because of the 5 digit restriction, the value resulting from the calculation may not be exact; but we do need it to be as accurate as possible. If I programmed it, in my inefficient, number-crunching way, the logic would have to be recursive, so as to get nearer to my 'perfect result' until the possibilities were exhausted.

But there may be a better way, which is why I've posted this.

To sum up (per example 2 above), a/b = 0.2048146, where a and b are positive integers, max 5 digits each. How close is it possible to get with a single division calculation? Can we get closer using 2 calculations with 4 unknowns e.g.: a/b * c/d = 0.2048146 ?

Thank you for reading and (I hope) understanding.

Best regards,

A non-mathematician.

There is a known efficient algorithm to find the nearest fraction with small terms to a given (decimal) number, using continued fractions. Excel presumably uses this when you format a cell as "Fraction" (up to 3 digits); when I give it 0.2048146, it displays 17/83, which is 0.204819277... .

Here is a page I wrote about this algorithm (with a slightly different goal than yours).

And here is another page I found with a search. This gives 1055/5151, which is 0.204814599... .

I'm sure there are other sources.
 
Thanks for posting those links, Peterson. Interesting info. :cool:
 
I am working on this (assuming that is I understand it. If not I apologize for wasting everyone's time.)

I have deleted this mess. Am still working.
 
Last edited:
After an embarrassing length of time, I realized that I was trying to do the impossible.

Using positive integers y and z, each of five digits, to represent any positive rational x is inherently imprecise. Any effort to create an algorithm that maintains a given degree of relative precision in all cases is doomed to fail.

\(\displaystyle x < 10^{-5}\) cannot be represented at all, and the relative error becomes large quite quickly as x decreases from there. Similarly, relative error grows quickly if x > 99999.

\(\displaystyle 10^{-4} < x < 10^{-5}\) does allow for some, but not all, potential values of x to be represented exactly. For example, 0.00004 can be represented as y = 2 and z = 50000. But if there are trailing digits after the 4, the potential relative error becomes quite significant. For example, consider x = 0.00001 with trailing digits. We have to set z = 99999, already an error, but let's analyze using z = 100000. Then y must equal 1 or 2. If x = 1.5, the relative error has a magnitude of 33% whichever choice we make. And that error is increased by using 99999 instead of 100000. So the range of error is approximately - 33% to + 33%. This is not confidence inspiring.

For \(\displaystyle 10^{-4} \ge x > 10^{-3}\), there are again some values that can be represented exactly, e.g x = 1/10000 = 0.0001. But if there are trailing digits, we again have issues. For example, what if we have something close to x = 0.00015. Then the obvious choices are y = 15 and z = 99999, but the relative error in that choice if x = 0.000155 is close to 5%, which may not be acceptable.

I do not say that an algorithm that is superior in terms of error reduction does not exist, but it is unlikely to be some simple, may be iterative, and probably will not reduce relative error to acceptable levels in all cases.

For \(\displaystyle 10^{-3} \le x\), we can derive a simple algorithm that reduces error to low levels. Consider x = 0.001004.
The obvious choices are y = 100 and z = 99999 \(\displaystyle \approx\) 0.00100001, with an error less than 1%.

I have not done a formal error analysis, but the following algorithm is simple and should give results that have a relative error that is better than plus or minus 1%.

\(\displaystyle x < 10^{-3} \implies \text {input out of bounds.}\)

\(\displaystyle x > 99999 \implies \text {input out of bounds.}\)

\(\displaystyle w = x + 0.000005.\)

\(\displaystyle w < 1 \implies y = \lfloor 99999w \rfloor \text { and } z = 99999.\)

\(\displaystyle 1 \le w \implies y = \lfloor w \rfloor \text { and } z = 1.\)

\(\displaystyle \dfrac{y}{z} \approx x.\)

Test it out. It should work. The variable w is close in value to x and has been half-adjusted to take trailing digits into account. The floor function insures y is an integer.

Let me know if you have questions.
 
Last edited:
JohnM16:

Have you tried the algorithm I suggested?

Looking for more information about it, here is a source that explains in what sense it gives the best possible answer:

For more detail, see section 4 of this paper:

Hi Folks,

a big thank you to all of you who replied to this, and especially Dr Peterson. His answer encompasses precisely what I was after - I had never heard of continued fractions.

I'm now going to go away and figure out how to program it using the wonderfully clunky language I work in (ABAP), which is great for reporting, less so for mathematics!

I'll try to report back with progress when I get a moment.

Thanks again,

John
 
Top