By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
457,911 Members | 1,213 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 457,911 IT Pros & Developers. It's quick & easy.

Avoiding float

P: n/a
I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.

Sep 7 '06 #1
Share this Question
Share on Google+
27 Replies


P: n/a
ga*****@hotmail.com wrote:
I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.
Hi!

Can you specify more clearly what you want to do? :-)

Konstantin
Sep 7 '06 #2

P: n/a
In article <11**********************@b28g2000cwb.googlegroups .com>,
<ga*****@hotmail.comwrote:
>I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow?
You will have to synthesize the arithmetic to do this, but it is not
difficult if you are only doing it for a pair.

Below, let W be the number of bits being multiplied at a time,
and let ** represent exponentiation

Then
(Ahigh * 2**W + Alow) * (Bhigh * 2**W + Blow) is

Ahigh * Bhigh * 2**(W+W) + Ahigh * Blow * 2**W +
Alow * Bhigh * 2**W + Alow * Blow

which is

(Ahigh * Bhigh) * 2**(2*W) +
(Ahigh * Blow + Alow * Bhigh) * 2**W +
Alow * Blow
Now the trick: let Ahigh be the high bits of the original unsigned long A
and let Alow be the low bits -- e.g.,

Alow = A & ~(1L<<W);
Ahigh = A >W;

and similiarily for Bhigh and Blow derived from B. For example, if your
unsigned long can hold 32 bits, you could let W be 16, and Ahigh would
be the top 16 bits of A and Alow would be the bottom 16 bits of A.

If you then multiply Alow * Blow and put the result into an
unsigned long, say T1, then the top W bits of that result are the "carry".
So you calculate Ahigh * Blow + Alow * Bhigh + (T1>>W) and that
gives you the next chunk of bits over -- except you have to
account for carries along the way. Say the result is in T2, then
the "low" unsigned long of the multiplication is
(T2 & ~(1L<<W)) << W | ((T1 & ~(1L<<W))

and so on, just making sure you take into account the carries at
each point. As long as the number of bits at a time that you operate
on does not exceed half the number of bits in an unsigned long,
then the result will always fit within an unsigned long, with the
top bits of that being the carry over to the next stage.
--
Is there any thing whereof it may be said, See, this is new? It hath
been already of old time, which was before us. -- Ecclesiastes
Sep 7 '06 #3

P: n/a
Konstantin Miller wrote:
ga*****@hotmail.com wrote:
I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Hi!

Can you specify more clearly what you want to do? :-)

Konstantin
I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.

Sep 7 '06 #4

P: n/a

ga*****@hotmail.com wrote:

I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.
Depends on how many liters. And how big your longs are.

You could multiply the liters by 26, then divide by 100.

*But* that means you can't have more than 2^32/26 or 2^64/26 liters to
start with.

So if you have less than 165191049 or 709490156681136600 liters, you
can do it.

Sep 7 '06 #5

P: n/a
ga*****@hotmail.com wrote:
Konstantin Miller wrote:
>ga*****@hotmail.com wrote:
>>I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Can you specify more clearly what you want to do? :-)

I have some long values in Liters and I want to convert to gallons
(and back). If I could do integer multiplication and divide by 10
I could avoid the float library. Thanks.
[1] c:\stds>units gallon litre
* 3.7854118
/ 0.26417205

As you can plainly see, the conversion factors are nowhere near
integral. Besides which, no float library should be required to do
the multiplication or division. The final output is another
matter.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Sep 7 '06 #6

P: n/a
ga*****@hotmail.com wrote:
Konstantin Miller wrote:
>ga*****@hotmail.com wrote:
>>I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Can you specify more clearly what you want to do? :-)

I have some long values in Liters and I want to convert to gallons
(and back). If I could do integer multiplication and divide by 10
I could avoid the float library. Thanks.
[1] c:\stds>units gallon litre
* 3.7854118
/ 0.26417205

As you can plainly see, the conversion factors are nowhere near
integral. Besides which, no float library should be required to do
the multiplication or division. The final output is another
matter.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>
Sep 7 '06 #7

P: n/a


ga*****@hotmail.com wrote On 09/07/06 13:53,:
Konstantin Miller wrote:
>>ga*****@hotmail.com wrote:

>>>I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Hi!

Can you specify more clearly what you want to do? :-)

Konstantin


I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.
Have you considered

long liters, gallons;
liters = ...whatever...;
gallons = liters * 3 / 10;

"Times three, over ten" is a crude approximation to 0.2641721,
but it's the only one I can think of that satisfies your desire
to divide by ten. If you're willing to consider other divisors,
more accurate conversions are possible:

gallons = liters * 26 / 100;
gallons = liters * 264 / 1000;
gallons = liters * 2642 / 10000;
...

You can convert from gallons back to liters the same way,
using various approximations to the conversion factor:

liters = gallons * 4;
liters = gallons * 38 / 10;
liters = gallons * 379 / 100;
...

However, all these conversions, no matter how accurate an
approximation you use, must eventually express the result as a
whole number of gallons or liters. You will need to chop or
round the "true" result to discard the fraction that a long
cannot express, and this introduces an unavoidable error: you
could be low by almost a gallon (if chopping, as shown) or either
high or low by as much as half a gallon (if rounding, not shown).

The error becomes especially nasty when you convert back
again, because the second conversion not only introduces its
own error (by discarding fractions of a liter), but also starts
from the slightly incorrect result of the first conversion. For
example, using the three-digit approximations above:

liters = 4;
gallons = liters * 264 / 1000;
liters = gallons * 339 / 100;

.... will yield liters==3 in the final step. There are at least
three ways to deal with this error:

- Switch to floating-point: There will still be errors, but
they will be much smaller. (For this kind of computation,
but not necessarily for all.)

- Switch to smaller units: Convert between milliliters and
teaspoons or some such. You'll still need to round or
chop, but the errors will be teaspoon-sized instead of
gallon-sized.

- Ignore it: Tell people the missing liter evaporated.

Your choice.

--
Er*********@sun.com

Sep 7 '06 #8

P: n/a
CBFalconer <cb********@yahoo.comwrites:
ga*****@hotmail.com wrote:
>Konstantin Miller wrote:
>>ga*****@hotmail.com wrote:

I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Can you specify more clearly what you want to do? :-)

I have some long values in Liters and I want to convert to gallons
(and back). If I could do integer multiplication and divide by 10
I could avoid the float library. Thanks.

[1] c:\stds>units gallon litre
* 3.7854118
/ 0.26417205

As you can plainly see, the conversion factors are nowhere near
integral. Besides which, no float library should be required to do
the multiplication or division. The final output is another
matter.
The exact ratio, in lowest terms, is 473176473 / 125000000 (or,
expressed as a real number, exactly 3.785411784). (1 liter is 1000
cubic centimeters; 1 US gallon is 231 cubic inches; 1 inch is 2.54
centimeters.)

I don't know where the "divide by 10" comes from, but I suspect the OP
is attempting to do premature optimization.

On most modern non-embedded systems, floating-point arithmetic is
implemented in hardware; only certain functions such as sqrt() and
sin() are implemented in software. If the intent is to improve the
performance of the code, using integer arithmetic rather than
floating-point arithmetic may not be at all helpful (but you can't
tell unless you've actually measured it).

Using exact rational arithmetic is one way to get exact results,
avoiding any possible rounding error, but that's seldom necessary for
gallon/liter conversions. The errors in measurement are likely to be
much larger than any rounding errors. (Be sure to use double, not
float, or use long double if you want even greater precision -- but
long double isn't necessarily more precise than double.)

If you want to do 64-bit integer arithmetic, check whether your
compiler supports "long long". It's new in C99, but many C90-ish
compilers support it as well. (Some compilers may provide a 64-bit
integer type with a different name; consult your documentation.)

There are also libraries for doing arbitrary-precision integer
artithmetic. GNU MP (GMP) is one such library.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Sep 7 '06 #9

P: n/a

<ga*****@hotmail.comwrote in message
news:11**********************@b28g2000cwb.googlegr oups.com...
>I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.
You can use a double and store the result as an integer * 10. The point of
doing this is that you don't have to mess about with non-standard types,
whilst still having integer arithmetic - you need to throw away the
fraction, of course.
--
www.personal.leeds.ac.uk/~bgy1mm
freeware games to download.
Sep 7 '06 #10

P: n/a
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
ga*****@hotmail.com wrote:
Konstantin Miller wrote:
ga*****@hotmail.com wrote:

I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Can you specify more clearly what you want to do? :-)

I have some long values in Liters and I want to convert to gallons
(and back). If I could do integer multiplication and divide by 10
I could avoid the float library. Thanks.
[1] c:\stds>units gallon litre
* 3.7854118
/ 0.26417205

As you can plainly see, the conversion factors are nowhere near
integral. Besides which, no float library should be required to do
the multiplication or division. The final output is another
matter.

The exact ratio, in lowest terms, is 473176473 / 125000000 (or,
expressed as a real number, exactly 3.785411784). (1 liter is 1000
cubic centimeters; 1 US gallon is 231 cubic inches; 1 inch is 2.54
centimeters.)

I don't know where the "divide by 10" comes from, but I suspect the OP
is attempting to do premature optimization.
[...]
Well I thought rather than using 3.785 I could use 3785 and then divide
the result by 1000. That is where my "divide by 10" comes from. Thanks.

Sep 7 '06 #11

P: n/a
Keith Thompson wrote:
CBFalconer <cb********@yahoo.comwrites:
>ga*****@hotmail.com wrote:
>>Konstantin Miller wrote:
ga*****@hotmail.com wrote:

I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Can you specify more clearly what you want to do? :-)

I have some long values in Liters and I want to convert to gallons
(and back). If I could do integer multiplication and divide by 10
I could avoid the float library. Thanks.

[1] c:\stds>units gallon litre
* 3.7854118
/ 0.26417205

As you can plainly see, the conversion factors are nowhere near
integral. Besides which, no float library should be required to do
the multiplication or division. The final output is another
matter.

The exact ratio, in lowest terms, is 473176473 / 125000000 (or,
expressed as a real number, exactly 3.785411784). (1 liter is 1000
cubic centimeters; 1 US gallon is 231 cubic inches; 1 inch is 2.54
centimeters.)
This is pure coincidence, but a few hours ago I published (here) my
ratapprx program for rational approximations. Applied to this
problem it gives:

[1] c:\c\ratapprx>ratapprx 3.7854118 10000
Usage: ratvalue [number [maxnumerator]]
number defaults to PI, maxnumerator to 500
Rational approximation to 3.785411800000000
2 / 1 = 2.000000000000000 with error 1.785411800000000
3 / 1 = 3.000000000000000 with error 0.785411800000000
4 / 1 = 4.000000000000000 with error 0.214588200000000
11 / 3 = 3.666666666666667 with error 0.118745133333333
15 / 4 = 3.750000000000000 with error 0.035411800000000
19 / 5 = 3.800000000000000 with error 0.014588200000000
34 / 9 = 3.777777777777778 with error 0.007634022222222
53 / 14 = 3.785714285714286 with error 0.000302485714286
458 / 121 = 3.785123966942149 with error 0.000287833057851
511 / 135 = 3.785185185185185 with error 0.000226614814815
564 / 149 = 3.785234899328859 with error 0.000176900671141
617 / 163 = 3.785276073619632 with error 0.000135726380368
670 / 177 = 3.785310734463277 with error 0.000101065536723
723 / 191 = 3.785340314136126 with error 0.000071485863874
776 / 205 = 3.785365853658536 with error 0.000045946341463
829 / 219 = 3.785388127853881 with error 0.000023672146119
882 / 233 = 3.785407725321889 with error 0.000004074678111
2699 / 713 = 3.785413744740533 with error 0.000001944740533
3581 / 946 = 3.785412262156448 with error 0.000000462156448
4463 / 1179 = 3.785411365564037 with error 0.000000434435963
8044 / 2125 = 3.785411764705882 with error 0.000000035294118

So I guess it has definite uses in allowing elimination of
overflows in calculations such as the OPs. I doubt if he needs
anything better than 882 / 233 (or 233 / 882 for the inverse
conversion). If he just installs the magic numbers without comment
he deserves anything that happens to him.

--
Chuck F (cbfalconer at maineline dot net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net>

Sep 7 '06 #12

P: n/a
CBFalconer <cb********@yahoo.comwrites:
This is pure coincidence, but a few hours ago I published (here) my
ratapprx program for rational approximations. Applied to this
problem it gives:

[1] c:\c\ratapprx>ratapprx 3.7854118 10000
[...]
8044 / 2125 = 3.785411764705882 with error 0.000000035294118
My HP 32SII calculator gives exactly the same approximation when
I type 3.7854118 and hit the FDISP (fraction display) button.[*]
Amazing.
[*] Well, it displays it as 3 1669 / 2125, but it's the same
fraction.
--
Ben Pfaff
email: bl*@cs.stanford.edu
web: http://benpfaff.org
Sep 7 '06 #13

P: n/a
Keith Thompson wrote:
I don't know where the "divide by 10" comes from, but I suspect the OP
is attempting to do premature optimization.
Avoiding floating point may itself be a premature optimization, and
without profiling a specific architecture, how do we actually know it
would be slower than integer arithmetic? FPU designs are pretty
sophisticated nowadays, and if it turns out that the FPU can do some
computations in its pipeline while the ALU is busy with other stuff, it
could very well turn out that float is no less efficient. This seems
even more likely when you're throwing in extra divide operations in
order to work with rational expressions.

But I'm not saying anything you didn't say already. As complicated as
pipeline architectures are, how do can you hope to guess what will be
efficient and what will not?
Sep 7 '06 #14

P: n/a
Ben Pfaff said:
CBFalconer <cb********@yahoo.comwrites:
>This is pure coincidence, but a few hours ago I published (here) my
ratapprx program for rational approximations. Applied to this
problem it gives:

[1] c:\c\ratapprx>ratapprx 3.7854118 10000

[...]
> 8044 / 2125 = 3.785411764705882 with error 0.000000035294118

My HP 32SII calculator gives exactly the same approximation when
I type 3.7854118 and hit the FDISP (fraction display) button.[*]
Amazing.
It might not be entirely coincidental. IIRC Chuck has done quite a bit of
work in the calculator industry. You might just be comparing his code
against - well, his code. :-)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Sep 7 '06 #15

P: n/a
ga*****@hotmail.com wrote:
Konstantin Miller wrote:
>ga*****@hotmail.com wrote:
>>I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.
Hi!

Can you specify more clearly what you want to do? :-)

Konstantin

I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.
Not so simple I'd guess. Have a look at this..

One survey foot = 0.3048006096 meters.
One statute mile = 1.6093472187 kilometers.
One inch = 0.0254 meters (exactly).
One foot = 0.3048 meters (exactly).
One yard = 0.9144 meters (exactly).
One cubic inch = 16.387064 cubic centimeters (exactly).
One cubic foot = 28.316846592 liters (exactly).
One cubic foot = 7.48051948 US gallons.
One US gallon = 3.785411784 liters (exactly).
One ounce (fluid) = 29.573529562 milliliters.
One pound = 453.59237 grams (exactly).
One pound = 7000 grains (exactly).
One ounce (avdp) = 28.349523125 grams (exactly).
One ounce (avdp) = 437.5 grains (exactly).
One grain = 64.79891 milligrams (exactly).
One carat = 3.08647167 grains.

One meter = 39.37007874 inches.
One meter = 3.280839895 feet.
One meter = 1.093613298 yards.
One kilogram = 2.204622622 pounds.
One gram = 15.43235835 grains.
One gram = 0.035273962 ounces.
One US gallon (water) weighs 8.345404 pounds.
Ten pounds of water is 1.198264 US gallons.

Doing stuff like this without floating point is something I don't want
to even think about.

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Sep 8 '06 #16

P: n/a

Walter Roberson wrote:
In article <11**********************@b28g2000cwb.googlegroups .com>,
<ga*****@hotmail.comwrote:
I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow?

You will have to synthesize the arithmetic to do this, but it is not
difficult if you are only doing it for a pair.

Below, let W be the number of bits being multiplied at a time,
and let ** represent exponentiation

Then
(Ahigh * 2**W + Alow) * (Bhigh * 2**W + Blow) is

Ahigh * Bhigh * 2**(W+W) + Ahigh * Blow * 2**W +
Alow * Bhigh * 2**W + Alow * Blow

which is

(Ahigh * Bhigh) * 2**(2*W) +
(Ahigh * Blow + Alow * Bhigh) * 2**W +
Alow * Blow
Now the trick: let Ahigh be the high bits of the original unsigned long A
and let Alow be the low bits -- e.g.,

Alow = A & ~(1L<<W);
Ahigh = A >W;

and similiarily for Bhigh and Blow derived from B. For example, if your
unsigned long can hold 32 bits, you could let W be 16, and Ahigh would
be the top 16 bits of A and Alow would be the bottom 16 bits of A.

If you then multiply Alow * Blow and put the result into an
unsigned long, say T1, then the top W bits of that result are the "carry".
So you calculate Ahigh * Blow + Alow * Bhigh + (T1>>W) and that
gives you the next chunk of bits over -- except you have to
account for carries along the way. Say the result is in T2, then
the "low" unsigned long of the multiplication is
(T2 & ~(1L<<W)) << W | ((T1 & ~(1L<<W))

and so on, just making sure you take into account the carries at
each point. As long as the number of bits at a time that you operate
on does not exceed half the number of bits in an unsigned long,
then the result will always fit within an unsigned long, with the
top bits of that being the carry over to the next stage.
How will you counter in case overflow happens for Ahigh * Blow + Alow *
Bhigh + (T1>>W) ? Over flow status flag must also be taken into
account.

-N

Sep 8 '06 #17

P: n/a
Eric Sosman wrote:
[...]
However, all these conversions, no matter how accurate an
approximation you use, must eventually express the result as a
whole number of gallons or liters. [...]
Not if I use some number of the least significant digits as a
"fractional" part. As you say the value is effectively in something
like milliliters. Thanks.

Sep 8 '06 #18

P: n/a

ga*****@hotmail.com wrote:
I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.
/*
An integral version will work OK if the quantities are huge, but breaks
down badly for small quantities.
*/

long gallons_to_liters(long gallons)
{
static const long long numerator = 31754337;
static const long long denominator = 8388608;
return (long) ((gallons * numerator) / denominator);
}

long liters_to_gallons(long liters)
{
static const long long numerator = 8388608;
static const long long denominator = 31754337;
return (long) ((liters * numerator) / denominator);
}

double g2l(double gallons)
{
return 3.785412 * gallons;
}

double l2g(double gallons)
{
return gallons / 3.785412;
}

#ifdef UNIT_TEST

#include <stdio.h>
#include <stdlib.h>

static char string[32767];
int main(void)
{
long gallons;
long liters;
puts("Enter gallons:");
fflush(stdout);
fgets(string, sizeof string, stdin);
gallons = atol(string);
printf("%ld gallons_to_liters = %ld liters\n", gallons,
gallons_to_liters(gallons));
printf("%ld g2l = %g liters\n", gallons,
g2l(gallons));

puts("Enter liters:");
fflush(stdout);
fgets(string, sizeof string, stdin);
liters = atol(string);
printf("%ld liters_to_gallons = %ld gallons\n", liters,
liters_to_gallons(liters));
printf("%ld l2g = %g gallons\n", liters,
l2g(liters));

return 0;
}
/*
C:\tmp>g2l2c
Enter gallons:
98765
98765 gallons_to_liters = 373866 liters
98765 g2l = 373866 liters
Enter liters:
373866
373866 liters_to_gallons = 98764 gallons
373866 l2g = 98764.9 gallons

C:\tmp>g2l2c
Enter gallons:
3
3 gallons_to_liters = 11 liters
3 g2l = 11.3562 liters
Enter liters:
11
11 liters_to_gallons = 2 gallons
11 l2g = 2.90589 gallons

C:\tmp>g2l2c
Enter gallons:
1
1 gallons_to_liters = 3 liters
1 g2l = 3.78541 liters
Enter liters:
3
3 liters_to_gallons = 0 gallons
3 l2g = 0.792516 gallons

*/
#endif

Sep 8 '06 #19

P: n/a
dc*****@connx.com writes:
ga*****@hotmail.com wrote:
>I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.

/*
An integral version will work OK if the quantities are huge, but breaks
down badly for small quantities.
*/
You can sometimes get decent results using fixed-point arithmetic. C
doesn't directly support this but you can, for example, use an integer
to represent a number of microliters or nanoliters.

Or you can just use floating-point, and the performance and precision
will probably be perfectly acceptable.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Sep 8 '06 #20

P: n/a
dc*****@connx.com wrote:
ga*****@hotmail.com wrote:
>I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs as
a 64 bit value somehow? Thanks.

/*
An integral version will work OK if the quantities are huge, but
breaks down badly for small quantities.
*/
To use the ratapprx program I published here earlier, I suggest the
following (untested) routine for the OP.

/* File mulrat.c */
#include "mulrat.h"

/* multiply an integral value by a rational fraction */
/* returns rounded product, -1 for overflow */
long int mulrat(long int value, /* to be processed */
const int num, /* numerator */
const int denom) /* denominator */
{
if (LONG_MAX / num < value + denom / 2) {
/* calculation will overflow */
return -1;
}
return ((value + denom/2) * num) / denom;
} /* mulrat */
/* File mulrat.h */
#ifndef H_mulrat_h
# ifdef __cplusplus
extern "C" {
# endif

#include <limits.h>

/* multiply an integral value by a rational fraction */
/* returns rounded product, -1 for overflow */
long int mulrat(long int value, /* to be processed */
const int num, /* numerator */
const int denom); /* denominator */

# ifdef __cplusplus
}
# endif
#endif

I repeat, untested code.

--
"The smaller aperture of the lid has been designed to prevent
hedgehogs from entering the McFlurry container in the
unfortunate incidence that the lid is littered"
-- McDonalds, as quoted in Time, 2006-09-11

Sep 8 '06 #21

P: n/a

Eric Sosman wrote:
ga*****@hotmail.com wrote On 09/07/06 13:53,:
Konstantin Miller wrote:
>ga*****@hotmail.com wrote:
I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.

Hi!

Can you specify more clearly what you want to do? :-)

Konstantin

I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.

Have you considered

long liters, gallons;
liters = ...whatever...;
gallons = liters * 3 / 10;

"Times three, over ten" is a crude approximation to 0.2641721,
but it's the only one I can think of that satisfies your desire
to divide by ten. If you're willing to consider other divisors,
more accurate conversions are possible:

gallons = liters * 26 / 100;
gallons = liters * 264 / 1000;
gallons = liters * 2642 / 10000;
...
picking something that is a power of two might be smart ;)

makes the division simple and also makes it easy to add up
fractions if you need to.

-Lasse

Sep 8 '06 #22

P: n/a
Keith Thompson wrote:
dc*****@connx.com writes:
>>ga*****@hotmail.com wrote:
>>>I need to do just a few multiplies of long integers and have a divide
by ten. Can I avoid using floats? Can I use two longs as a 64 bit value
somehow? Thanks.

/*
An integral version will work OK if the quantities are huge, but breaks
down badly for small quantities.
*/


You can sometimes get decent results using fixed-point arithmetic. C
doesn't directly support this but you can, for example, use an integer
to represent a number of microliters or nanoliters.
This is the solution I have used on a number of embedded control
applications where floating point requires expensive library calls.
Pick the accuracy you require and the minimum sized integer that gives
you adequate headroom and scale the values appropriately.

In most of my applications, the inputs have been analogue voltages,
currents and temperatures where milli-whatevers have been accurate
enough for the application.
Or you can just use floating-point, and the performance and precision
will probably be perfectly acceptable.
Assuming an FPU.

--
Ian Collins.
Sep 8 '06 #23

P: n/a
In article <od******************************@comcast.comJoe Wright <jo********@comcast.netwrites:
ga*****@hotmail.com wrote:
....
I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.

Not so simple I'd guess. Have a look at this..
Let's see. 1 US gallon is 231 cubic inches. 1 inch is 2.54 cm.
1000 cubic cm is 1 liter. So 1 (US) gallon is 3.785411784 liter
exactly. And 1 UK gallon is 4.54609 liter exactly. So converting
liters to gallons can not be done with only division by 10, but it
can be done the other way around. (This is all according to the
latest standards.)

But let me see:
One survey foot = 0.3048006096 meters.
1200 / 3937 exactly.
One statute mile = 1.6093472187 kilometers.
6336 / 3937 exactly.
One cubic foot = 7.48051948 US gallons.
1728 / 231 exactly.
One US gallon = 3.785411784 liters (exactly).
Indeed.
One ounce (fluid) = 29.573529562 milliliters.
29.5735295625 ml (473176473 / 16000000) exactly (for the US fluid ounce)
28.4130625 ml (454609 / 16000) exactly (for the UK fluid ounce)
Doing stuff like this without floating point is something I don't want
to even think about.
The conversion factors are all plain rational numbers. In the US that
is the case since 1866 and in the UK since 1995. So doing this with
integer operations only is very viable. (Yes, 1866 was not an error.)
The difference in the US between the survey foot and the standard foot
comes because originally (1866) the US linked the foot to the meter
by a reverse factor to that introduced in 1963. The original foot
remained in use in surveying. Something similar did happen with the
US pound, but here the original pound is no longer used (1 kg =
2.2046 lb in 1866, in 1893 adapted to 2.20462 and in 1894 to 2.20462234).
In 1959 changed to the current definition that was also adopted in the
UK in 1963.

But *all* measures in the US are tightly linked, through rational
conversion factors, to the metric system since 1866.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Sep 9 '06 #24

P: n/a
Dik T. Winter wrote:
In article <od******************************@comcast.comJoe Wright <jo********@comcast.netwrites:
ga*****@hotmail.com wrote:
...
I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.
>
Not so simple I'd guess. Have a look at this..

Let's see. 1 US gallon is 231 cubic inches. 1 inch is 2.54 cm.
1000 cubic cm is 1 liter. So 1 (US) gallon is 3.785411784 liter
exactly. And 1 UK gallon is 4.54609 liter exactly. So converting
liters to gallons can not be done with only division by 10, but it
can be done the other way around. (This is all according to the
latest standards.)

But let me see:
One survey foot = 0.3048006096 meters.

1200 / 3937 exactly.
One statute mile = 1.6093472187 kilometers.

6336 / 3937 exactly.
One cubic foot = 7.48051948 US gallons.

1728 / 231 exactly.
One US gallon = 3.785411784 liters (exactly).

Indeed.
One ounce (fluid) = 29.573529562 milliliters.

29.5735295625 ml (473176473 / 16000000) exactly (for the US fluid ounce)
28.4130625 ml (454609 / 16000) exactly (for the UK fluid ounce)
Doing stuff like this without floating point is something I don't want
to even think about.

The conversion factors are all plain rational numbers. In the US that
is the case since 1866 and in the UK since 1995. So doing this with
integer operations only is very viable. (Yes, 1866 was not an error.)
The difference in the US between the survey foot and the standard foot
comes because originally (1866) the US linked the foot to the meter
by a reverse factor to that introduced in 1963. The original foot
remained in use in surveying. Something similar did happen with the
US pound, but here the original pound is no longer used (1 kg =
2.2046 lb in 1866, in 1893 adapted to 2.20462 and in 1894 to 2.20462234).
In 1959 changed to the current definition that was also adopted in the
UK in 1963.

But *all* measures in the US are tightly linked, through rational
conversion factors, to the metric system since 1866.
All this is trivial, I know, but I remain fascinated.

Using your UK ounce and multiplying by 160 for a UK gallon, I get
4546.09 milliliters. Dividing that by grams per pound gives 10.022412855
pounds per UK gallon. The Imperial Gallon was 10 pounds exactly.

How shall we accommodate this gross inaccuracy? Revisit the
International Standards somehow? :=)

In fun..

--
Joe Wright
"Everything should be made as simple as possible, but not simpler."
--- Albert Einstein ---
Sep 9 '06 #25

P: n/a
In article <Rp******************************@comcast.comJoe Wright <jo********@comcast.netwrites:
Dik T. Winter wrote:
....
All this is trivial, I know, but I remain fascinated.
Not so very trivial.
Using your UK ounce and multiplying by 160 for a UK gallon, I get
4546.09 milliliters. Dividing that by grams per pound gives 10.022412855
pounds per UK gallon. The Imperial Gallon was 10 pounds exactly.
It was. Since 1963 it was 10 pounds of water with density 0.998859 gr/ml
weighed in air of density 0.001217 gr/ml against weights of density
8.136 gr/ml. Weights and Measures Bill (G.B.), HC 70 (1963). Now
calculate the volume. Unless I seriously misunderstood Archimedes I
come at 1 gallon = 368987550040571 / 81168153120 ml, or about
4545.96459 ml.

And I think it is; just tweak some of the densities. With the densities
of 1963 I come at 3689977292173008 / 368987550040571 or about
10.0002758678 pounds. Slightly better than you think, I would say.
Offhand I would not know densities of similar precision that give the
same result, but I think those might exist.
--
dik t. winter, cwi, kruislaan 413, 1098 sj amsterdam, nederland, +31205924131
home: bovenover 215, 1025 jn amsterdam, nederland; http://www.cwi.nl/~dik/
Sep 10 '06 #26

P: n/a
Joe Wright wrote:
ga*****@hotmail.com wrote:
>Konstantin Miller wrote:
>>ga*****@hotmail.com wrote:

I need to do just a few multiplies of long integers and have a
divide by ten. Can I avoid using floats? Can I use two longs
as a 64 bit value somehow? Thanks.
Hi!

Can you specify more clearly what you want to do? :-)

Konstantin

I have some long values in Liters and I want to convert to gallons (and
back). If I could do integer multiplication and divide by 10 I could
avoid the float library. Thanks.

Not so simple I'd guess. Have a look at this..

One survey foot = 0.3048006096 meters.
One statute mile = 1.6093472187 kilometers.
One inch = 0.0254 meters (exactly).
One foot = 0.3048 meters (exactly).
One yard = 0.9144 meters (exactly).
One cubic inch = 16.387064 cubic centimeters (exactly).
One cubic foot = 28.316846592 liters (exactly).
One cubic foot = 7.48051948 US gallons.
One US gallon = 3.785411784 liters (exactly).
One ounce (fluid) = 29.573529562 milliliters.
One pound = 453.59237 grams (exactly).
One pound = 7000 grains (exactly).
One ounce (avdp) = 28.349523125 grams (exactly).
One ounce (avdp) = 437.5 grains (exactly).
One grain = 64.79891 milligrams (exactly).
One carat = 3.08647167 grains.

One meter = 39.37007874 inches.
One meter = 3.280839895 feet.
One meter = 1.093613298 yards.
One kilogram = 2.204622622 pounds.
One gram = 15.43235835 grains.
One gram = 0.035273962 ounces.
One US gallon (water) weighs 8.345404 pounds.
Ten pounds of water is 1.198264 US gallons.

Doing stuff like this without floating point is something I don't want
to even think about.
I take it you do not write embedded code.
I assume the OP is or why ask the question.
floating point is slow and uses a large chunk of RAM and ROM.
The required accuracy is what fits on the display.
besides even on big iron floating point has it's own issues.
Sep 12 '06 #27

P: n/a
ga*****@hotmail.com wrote:
Eric Sosman wrote:
>[...]
However, all these conversions, no matter how accurate an
approximation you use, must eventually express the result as a
whole number of gallons or liters. [...]

Not if I use some number of the least significant digits as a
"fractional" part. As you say the value is effectively in something
like milliliters. Thanks.
A lot of theory here.
If you want a real solution.
The range of liters.
The range of gallons.
The number of significant digits you want to display.
Sep 12 '06 #28

This discussion thread is closed

Replies have been disabled for this discussion.