Java Forum / General / December 2005
double precision vs. integers
Andersen - 18 Dec 2005 12:42 GMT I want to take power of something, or the logarithm of something, with different bases. the Math.* are only defined for doubles, how do I do these operations if I am sure that everything is a perfect integer log or a perfect power (integer).
Andersen - 18 Dec 2005 12:45 GMT > I want to take power of something, or the logarithm of something, with > different bases. the Math.* are only defined for doubles, how do I do > these operations if I am sure that everything is a perfect integer log > or a perfect power (integer). I extend that question to ceiling and floor which return integers/longs.
O.L. - 18 Dec 2005 13:45 GMT Andersen a écrit :
> I want to take power of something, or the logarithm of something, with > different bases. the Math.* are only defined for doubles, how do I do these > operations if I am sure that everything is a perfect integer log or a perfect > power (integer). int a = 5; int b = 2; int pow = (int) Math.pow(a, b);
?
 Signature Olivier Ligny Créateur web free-lance / www.cyber-tamtam.net
Andersen - 18 Dec 2005 16:06 GMT > int a = 5; > int b = 2; > int pow = (int) Math.pow(a, b); I want the results to be precise and not have any mishaps because of the conversion.
Mark Thornton - 18 Dec 2005 16:14 GMT >> int a = 5; >> int b = 2; >> int pow = (int) Math.pow(a, b); > > I want the results to be precise and not have any mishaps because of the > conversion. The specification of Math.pow() includes this
"If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power of the second argument if that result can in fact be represented exactly as a double value"
Thus if the arguments are integers and the result is within the range of int, then the expression given will be correct. This is one of the advantages of Java's specification; it provides useful guarantees in circumstances like this.
Mark Thornton
Googmeister - 18 Dec 2005 16:14 GMT > > int a = 5; > > int b = 2; > > int pow = (int) Math.pow(a, b); > > I want the results to be precise and not have any mishaps because of the > conversion. Not a problem with Math.pow since all values of type int are exactly representable using type double. According to the API
If both arguments are integers, then the result is exactly equal to the mathematical result of raising the first argument to the power of the second argument if that result can in fact be represented exactly as a double value.
Thomas Weidenfeller - 19 Dec 2005 13:51 GMT > I want the results to be precise and not have any mishaps because of the > conversion. Well, you might want your logarithms "to be precise" in integer notation, but I am afraid, the odds are very much against you.
logarithms of negative numbers result in complex numbers, so lets forget about negative numbers at all.
For positive integers, lets take a logarithm where there is some chance of getting exact results: A logarithm for the base 2 [1]. Then for a 31 bit integer (32 bits minus the sign bit), there are only 32 out of 2147483647 possible integers (the 0 included) where the base 2 logarithm fits exactly into an integer[1].
That is roughly a chance of one in 67 million to get an exact result for a random non negative integer argument from a base 2 logarithm.
I think you should reconsider your requirements.
/Thomas
[1] Logarithm computating degenerates into bit counting in this case.
[2] All cases where there is only a single bit true within the 31 bits, plus when all are false (the 0).
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Eric Sosman - 19 Dec 2005 20:32 GMT Thomas Weidenfeller wrote On 12/19/05 08:51,:
>>I want the results to be precise and not have any mishaps because of the >>conversion. [quoted text clipped - 10 lines] > 2147483647 possible integers (the 0 included) where the base 2 logarithm > fits exactly into an integer[1]. ITYM 31 cases, or else you've come up with a new way of defining the logarithm of zero. (Also, if "the 0 included" then why only 2147483647 possible integers instead of ...8?)
> That is roughly a chance of one in 67 million to get an exact result for > a random non negative integer argument from a base 2 logarithm. Well, he could use other bases to improve his odds. Base-two logarithms cover the 31 values 1,2,4,...,1073741824. Base-three covers 1,3,9,...,1162261467; the 1 is a duplicate so that's 19 more values for a total of 50. Base-five gives 1,5,25,...,1220703125 and raises the total to 63 (we've already doubled the oroginal coverage), and so on for other bases. For the ultimate simplification, he can define
static int exactLog(int n) { if (n <= 0) throw new IllegalArgumentException(); return 1; }
... with the appropriate logarithmic base implied ;-)
 Signature Eric.Sosman@sun.com
Andersen - 19 Dec 2005 22:53 GMT > ITYM 31 cases, or else you've come up with a new way > of defining the logarithm of zero. (Also, if "the 0 included" > then why only 2147483647 possible integers instead of ...8?) ...
>>That is roughly a chance of one in 67 million to get an exact result for >>a random non negative integer argument from a base 2 logarithm. [quoted text clipped - 6 lines] > doubled the oroginal coverage), and so on for other bases. > For the ultimate simplification, he can define The bigger the base the fewer numbers fit in the double, not the other way around.
> static int exactLog(int n) { > if (n <= 0) > throw new IllegalArgumentException(); > return 1; > } For a fact, my program will never be invoked with log_k(k), or there is something fishy with the postcondition of some other function.
Eric Sosman - 19 Dec 2005 23:15 GMT Andersen wrote On 12/19/05 17:53,:
>> ITYM 31 cases, or else you've come up with a new way >>of defining the logarithm of zero. (Also, if "the 0 included" [quoted text clipped - 15 lines] > The bigger the base the fewer numbers fit in the double, not the other > way around. Yes, but with several bases you can cover more numbers than with just one.
>> static int exactLog(int n) { >> if (n <= 0) [quoted text clipped - 4 lines] > For a fact, my program will never be invoked with log_k(k), or there is > something fishy with the postcondition of some other function. You snipped and apparently overlooked the ;-)
The function as shown correctly computes the logarithm of any positive integer. It does this by using an adaptive technique, choosing a base that permits the calculation to be exact. For example, exactLog(2) computes a binary logarithm, exactLog(10) computes a decimal logarithm, and exactLog(42) computes a base-42 logarithm. 100% effective, 100% exact, and surprisingly efficient. I'll grant that it has a few drawbacks, but hey ...
 Signature Eric.Sosman@sun.com
Thomas Weidenfeller - 20 Dec 2005 09:16 GMT > ITYM 31 cases, or else you've come up with a new way > of defining the logarithm of zero. Ups :-)
> (Also, if "the 0 included" > then why only 2147483647 possible integers instead of ...8?) Because, ahem, because, aehm, aehm, well :-)
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Roedy Green - 19 Dec 2005 22:27 GMT On Mon, 19 Dec 2005 14:51:04 +0100, Thomas Weidenfeller <nobody@ericsson.invalid> wrote, quoted or indirectly quoted someone who said :
>That is roughly a chance of one in 67 million to get an exact result for >a random non negative integer argument from a base 2 logarithm. But by that thinking the number 42 is impossible. It is immeasurable small on the real line, and only a blip in the universe of doubles.
If he is working with only integers, if he squares one, the odds of a sqrt giving a int result are much improved. Ditto for log and exp.
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Andersen - 19 Dec 2005 22:45 GMT > Well, you might want your logarithms "to be precise" in integer > notation, but I am afraid, the odds are very much against you. [quoted text clipped - 12 lines] > > I think you should reconsider your requirements. Hope you had a little fun there. I have an application where I know the numbers are powers of some base k, and I want their logarithm. I could resort to bit counting and then divide by log_2(k), but I am afraid that will lead to rouding errors because of the way floating point numbers are represented.
Eric Sosman - 19 Dec 2005 23:00 GMT Andersen wrote On 12/19/05 17:45,:
>>Well, you might want your logarithms "to be precise" in integer >>notation, but I am afraid, the odds are very much against you. [quoted text clipped - 18 lines] > will lead to rouding errors because of the way floating point numbers > are represented. static int logBaseK(int n, int k) { return (int)Math.round(Math.log(n) / Math.log(k)); }
Yes, there will be inaccuracies in computing the two logs, and probably in computing their quotient. But the inaccuracies will be small (assuming legitimate n and k), and will be fixed by the Math.round() call.
You could do an all-integer (or -long) version using repeated multiplication: start with 1, multiply by k until you get n, and return the count. You'd never need more than 30 (62) iterations in the worst legitimate case.
Error-checking (in both versions) is left as an exercise for the reader.
 Signature Eric.Sosman@sun.com
Chris Uppal - 20 Dec 2005 09:55 GMT > You could do an all-integer (or -long) version using > repeated multiplication: start with 1, multiply by k until > you get n, and return the count. You'd never need more > than 30 (62) iterations in the worst legitimate case. Or a table lookup (probably with a binary chop or similar).
-- chris
Thomas Weidenfeller - 20 Dec 2005 10:02 GMT > Hope you had a little fun there. Sure, nothing in the group's charter prohibits having a bit of fun.
And as a general hint, playing with then numbers and some formulas when you have a math problem at hand doesn't hurt. It gives you some feel for the problem.
> I have an application where I know the > numbers are powers of some base k, k being a positive integer? Why didn't you tell us this upfront? You could e.g. handle that problem with a lookup table. E.g for a base 2 a table of 31 integers if you really don't trust log():
final static int logs2[] = { 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010, 0x00000020, 0x00000040, 0x00000080, 0x00000100, 0x00000200, 0x00000400, 0x00000800, 0x00001000, 0x00002000, 0x00004000, 0x00008000, 0x00010000, 0x00020000, 0x00040000, 0x00080000, 0x00100000, 0x00200000, 0x00400000, 0x00800000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000, 0x20000000, 0x40000000 };
final static int logs3[] = { 1, 3, 9, 27, ... };
private int binSearch(int values[], int e) throws ImpreciseException { int l = 0; int r = values.length - 1; int p; while(l <= r) { p = (l + r) / 2; if(e == values[p]) return p; if(e < values[p]) { r = p - 1; } else { l = p + 1; } } throw new ImpreciseException(); }
public int preciseLog2(int e) throws ImpreciseException { return binSearch(logs2, e); }
public int preciseLog3(int e) throws ImpreciseException { return binSearch(logs3, e); }
/Thomas
 Signature The comp.lang.java.gui FAQ: ftp://ftp.cs.uu.nl/pub/NEWS.ANSWERS/computer-lang/java/gui/faq http://www.uni-giessen.de/faq/archiv/computer-lang.java.gui.faq/
Andersen - 20 Dec 2005 11:02 GMT > k being a positive integer? Why didn't you tell us this upfront? You > could e.g. handle that problem with a lookup table. E.g for a base 2 a > table of 31 integers if you really don't trust log(): That is fine if you need 5 different k's, if you want something general you need more tables. Given what I said earlier that I am not interested in the trivial logarithm: log_k(k), that would mean we need floor(sqrt(2^n)) tables for a n bit numbers. Only for 31 bits that would be some 46340 tables or so. I suppose you could generate these in a list of lists... The only limit would be the memory, it would take 100kb of memory or so, not much for a PC, huge for a smaller device under MIDP.
Roedy Green - 18 Dec 2005 16:18 GMT On Sun, 18 Dec 2005 13:42:43 +0100, Andersen <andersen_800@hotmail.com> wrote, quoted or indirectly quoted someone who said :
>I want to take power of something, or the logarithm of something, with >different bases. the Math.* are only defined for doubles, how do I do >these operations if I am sure that everything is a perfect integer log >or a perfect power (integer). You can take your answer then round it and see if it matches exactly.
see http://mindprod.com/jgloss/round.html
 Signature Canadian Mind Products, Roedy Green. http://mindprod.com Java custom programming, consulting and coaching.
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|