Android Question I Need Sub Code that Can Compute Large and Very Large Exponential

omo

Active Member
Licensed User
Longtime User
I need b4x code that can compute large and very large exponential like 3^935687429879864897 or more. Answer to this sample should be: 2.19222399769E+446436360569697305

I have tried different methods and algorithms to no effect. I also tried some AI, but couldn't get right code with stable solution.

I tried also to use Bigdecimal library in the forum, once the exponent digits is more than 5 or 6, the app hangs and force to restart. Try and catch couldn't solve it either.

If your solution can solve this even if it is using java object in b4x or bigdecimals in b4x ( in case I didn't use it well) or other algorithms, I don't mind. So far your solution can solve this and more:

3^935687429879864897 and get this result: 2.19222399769E+446436360569697305 or close to it.
Then, your solution should be ok and robust enough to handle more or less

Thank you in advance
 
Last edited:
Solution
Here another example.

B4X pages project using this library with Inline Java. Tested with B4J.

The result: 2.19222399769E+446436360569697305

Copy big-math-2.3.2.jar to the B4J additional libraries folder.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    ' Inline Java object
    Private joInlineJava As JavaObject = Me
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
End Sub

Private Sub Button1_Click
    ' Example: compute 3^935687429879864897 with 12 digits
    Dim result As String
    result =...

Theera

Expert
Licensed User
Longtime User
I think you can use AI Prompt "I need b4x code that can compute large and very large exponential like 3^935687429879864897 or more. Answer to this sample should be: 2.19222399769E+446436360569697305 in B4X's function module"
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
I think you can use AI Prompt "I need b4x code that can compute large and very large exponential like 3^935687429879864897 or more. Answer to this sample should be: 2.19222399769E+446436360569697305 in B4X's function module"
I already pointed out I did that but couldn't get solution. See here in my text:

....I have tried different methods and algorithms to no effect. I also tried some AI, but couldn't get right code with stable solution..
I purposely put: 3^935687429879864897 and it's answer: 2.19222399769E+446436360569697305 ; so that it will be helpful for whosoever want to help me with the code to test the code with it and answer. I am not looking for answer to only that alone, the code should be able to solve other inputs that is not limited to my test case. Hope it is more clearer now?
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Longtime User
I'm doing this on the fly, but... I think if you calculate using base 10 logarithms, where your example result:

2.19222399769E+446436360569697305

is the same as:

2.19222399769 * 10 ^ 446436360569697305

and thus its logarithm is:

= Log10(2.19222399769) + 446436360569697305
= 0.34088492754 + 446436360569697305
= 446436360569697305 + 0.34088492754
= 446436360569697305.34088492754

then it should be possible, although the problem is that if we're confined to using Intel FPU data types then the most resolution we're going to have is the intermediate 80-bit floating point type, and that "only" has 64 bits of precision ie 19 decimal digits, and nearly all of that is going to be swallowed up representing the exponent of the logarithm, so...

how precise does the answer need to be? And, more interestingly, why?
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
B4X:
Dim A As Double = 3
Dim B As Double = 935687429879864897

If True Then    'test case that doesn't overflow Double precision type
    A = 123
    B = 45
    Log(A & TAB & B & TAB & Power(A, B))
End If

Dim LogA As Double = Logarithm(A, 10)
Dim LogApowerB As Double = LogA * B

Dim IntLog As Double = Floor(LogApowerB)
Dim FracLog As Double = LogApowerB - IntLog

Dim ResultMantissa As Double = Power(10, FracLog)
Dim ResultExponent As Double = IntLog

Log(A & TAB & B)
Log(LogA & TAB & LogApowerB)
Log(FracLog & TAB & IntLog)

'''Log(ResultMantissa & " E " & ResultExponent)    'only displays first ~17 digits of ResultExponent
Log(ResultMantissa & " E " & NumberFormat2(ResultExponent, 1, 3, 3, False))

Log output for 123 ^ 45:
Waiting for debugger to connect...
Program started.
123    45    1.1110408185131957E94
123    45
2.0899051114393976    94.04573001477289
0.04573001477288585    94
1.1110408185131417 E 94.000
Program terminated (StartMessageLoop was not called).

Log output for 3 ^ 935687429879864897:
Waiting for debugger to connect...
Program started
3    9.3568742987986496E17
0.47712125471966244    4.4643636056969734E17
0    4.4643636056969734E17
1 E 446436360569697340.000
Program terminated (StartMessageLoop was not called).

The exponent is in the ballpark of your (presumably) correct 446436360569697305, ie first 16 digits match, but precision beyond that has been lost due to Double floating point mantissa being 53-54 bits out of 64.
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
I tried same thing in PowerBasic with 80-bit floats instead of 64:

B4X:
DEFEXT A-Z

A = 3
B = 935687429879864897

IF 0 THEN    'test case that doesn't overflow Double precision type
    A = 123
    B = 45
    PRINT A, B, A ^ B
END IF

LogA = LOG10(A)
LogApowerB = LogA * B

IntLog = INT(LogApowerB)
FracLog = LogApowerB - IntLog

ResultMantissa = 10 ^ FracLog
ResultExponent = IntLog

PRINT A, B
PRINT LogA, LogApowerB
PRINT FracLog, IntLog

PRINT ResultMantissa; "E"; ResultExponent    'only displays first ~16 digits of ResultExponent
PRINT ResultMantissa; "E " ; FORMAT$(ResultExponent, "0.000")

and it got closer to the full result (exponent is correct, but only a few bits of precision were left for the mantissa) :

Program output:
 3             9.35687429879865E+17
 .477121254719662            4.46436360569697E+17
 .375          4.46436360569697E+17
 2.37137370566166 E 4.46436360569697E+17
 2.37137370566166 E 446436360569697305.000

so all we need to do now is find ourselves a working VAX running BASIC and we'd probably have a matching mantissa too:

 
Upvote 0

Peter Simpson

Expert
Licensed User
Longtime User
Hello,
I've not tried this myself, it may help, it may not. I just know that this library has something to do with big numbers.

 
Upvote 0

omo

Active Member
Licensed User
Longtime User
Thank you @emexes for all these attempts. Now, you made me know the reason why I was getting 1E at the mantissa while exponent was always correct. So, it was due to precision lost

I had tried this logarithm approach before reaching out for forum help, but didn't know the reason while I was always getting 1E as mantissa with correct exponent. However, if I use another app in my phone, I get instant answer no matter how large what I input. So, I am curious while can't I do the same with b4x? And that is why I am trying to look for solution in b4x

Can you use bigdecimals for this your logarithm approach? Are we going to get all correct answer without loss in precision?
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
Thank you @ Peter for this reference. It was one of my first attempts I reached out to in order to solve this problem, but it wasn't working as I expected for large exponentiation as I said in my question above that once the exponent digits are more than 5 or 6, then; it hangs and restarts the app.

I don't know maybe I didn't implement it well, but I had used this bigdecimal library for others that worked well, but couldn't just couldn't handle large exponent above 6 digits. Maybe it because the pow method in this bigdecimal expects "int data type" in its argument instead of biginteger or bigdecimal. I guess that maybe the reason why it is hanging after 6 digits of exponent passed.

What I intend doing now is to write customized user defined "pow function" that will accept bigdecimal or biginteger and use it instead of existing pow in bigdecimal.
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
How I wish there is #if VaxBasic ...#endif in b4x, then; I can easily use it to solve this problem. I just need b4x solution or java object or otherwise that can be used to solve this problem in b4x.

On a joke part, I don't even know Vax basic exists, I am hearing it for the first time in my life. I only briefly used GW-Basic or QBasic when it was dieing off and I read many other extensive versions existence in books even though not used. But I never used or read about VaxBasic before. Visual Basic 6 was my first serious basic, but I don't care if it can be embedded in b4x to solve this problem, then; I welcome it. How do you still get this environment to run this old Basic? I will even love to warm my brain with QBasic environment once more even if it is one time in a year
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
Got this result
Result: 3.6573543923 E446436360569697303

using this code (written with help of Copilot)
B4X:
#if java
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;

public static void power(String n, String exp) {
    BigDecimal base = new BigDecimal(n);
    BigDecimal exponent = new BigDecimal(exp);

    MathContext mc = new MathContext(60, RoundingMode.HALF_UP); // High precision

    // log10(3) ≈ 0.47712125472
    BigDecimal log10Base = new BigDecimal(Math.log10(base.doubleValue()), mc);
    BigDecimal log10Result = exponent.multiply(log10Base, mc);

    // Extract exponent and fractional part
    BigDecimal exponentPart = log10Result.setScale(0, RoundingMode.FLOOR);
    BigDecimal fractionalPart = log10Result.subtract(exponentPart, mc);

    // Use fractional part to estimate mantissa via log rules:
    // mantissa ≈ 10^fractionalPart
    double mantissa = Math.pow(10, fractionalPart.doubleValue());

    System.out.printf("Result: %.10f E%s%n", mantissa, exponentPart.toPlainString());
}
#End If

called like
B4X:
Me.as(JavaObject).RunMethod("power",Array("3","935687429879864897"))
 
Upvote 0

rwblinn

Well-Known Member
Licensed User
Longtime User
Here another example.

B4X pages project using this library with Inline Java. Tested with B4J.

The result: 2.19222399769E+446436360569697305

Copy big-math-2.3.2.jar to the B4J additional libraries folder.

B4X:
Sub Class_Globals
    Private Root As B4XView
    Private xui As XUI
    ' Inline Java object
    Private joInlineJava As JavaObject = Me
End Sub

Public Sub Initialize
'    B4XPages.GetManager.LogEvents = True
End Sub

'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
    Root = Root1
    Root.LoadLayout("MainPage")
End Sub

Private Sub Button1_Click
    ' Example: compute 3^935687429879864897 with 12 digits
    Dim result As String
    result = joInlineJava.RunMethod("HugePowerSci", Array("3", "935687429879864897", 12))
   
    Log(result)    ' > 2.19222399769E+446436360569697305
    xui.MsgboxAsync($"3^935687429879864897 = ${result}"$, "HugePower Result")
End Sub

#If JAVA
import ch.obermuhlner.math.big.BigDecimalMath;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;

public String HugePowerSci(String baseStr, String expStr, int digits) {
    try {
        import java.math.BigDecimal;
        import java.math.BigInteger;
        import java.math.MathContext;
        import ch.obermuhlner.math.big.BigDecimalMath;

        BigDecimal base = new BigDecimal(baseStr);
        BigInteger exp = new BigInteger(expStr);
        MathContext mc = new MathContext(digits + 50); // high precision

        // log10(base)
        BigDecimal log10Base = BigDecimalMath.log10(base, mc);

        // exponent * log10(base)
        BigDecimal exponentTimesLog = new BigDecimal(exp).multiply(log10Base, mc);

        // integer and fractional parts
        BigInteger intPart = exponentTimesLog.toBigInteger();
        BigDecimal fracPart = exponentTimesLog.subtract(new BigDecimal(intPart), mc);

        // significand = 10^fractional_part
        BigDecimal significand = BigDecimalMath.pow(BigDecimal.TEN, fracPart, mc);

        // round to requested digits
        significand = significand.round(new MathContext(digits));

        return significand.toPlainString() + "E+" + intPart.toString();
    } catch (Exception e) {
        return "Error: " + e.getMessage();
    }
}
#End If
 

Attachments

  • HugePower.zip
    56.1 KB · Views: 28
Last edited:
Upvote 0
Solution

omo

Active Member
Licensed User
Longtime User
This is good attempt for java bigdecimal, thank you; it is even better than one of my solutions where I got 5... while the exponent is correct, but I can't still rely on such answer because this difference is still huge. Getting 3.6573543923 compare to 2.19222399769 is still huge, it might not be stable for other larger or smaller solutions.

The + or - error gap is still much here. If it can be twisted to get 2.1... 2.5... and if consistent with other inputs, then it may be considered correct. Me and java are not friends, but I can only make minor correction here to twist it further maybe I will get closer result or if you can help.me twist it further to get closer result in acceptable tolerance error range.
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
Thank you, I will try it and get back; but I already seen hope and solution in it.
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
Very accurate and doesn't lag! Thank you so much @rwblinn and @emexes, @Theera,.@Peter Simpson, @Daestrum and others making attempt to help. This solution works well. I used it in b4a environment, remember to add #AdditionalJar: big-math-2.3.2 in main as reference to jar copied in additional library folder once downloaded from the link he pointed out.

For those of us that are still partial enemies to java, I would not mind if all.othet methods that are meant for bigdecimals cases can be listed for us in java object like this or wrap to b4a/b4j for easy usage where bignumber (Bigdecimal/biginteger) in the forum lacks. Thank you all. I marked this as solution
 
Last edited:
Upvote 0

emexes

Expert
Licensed User
Longtime User
the reason why I was getting 1E at the mantissa while exponent was always correct. So, it was due to precision lost

I'm pretty sure this is effectively the reason why. A Double has 16 digits of precision to represent the logarithm, and the more digits that are in front of the decimal point to represent the exponent, the less are available after the decimal point to represent the mantissa. And once the logarithm is over 2^53 (or maybe 2^54) then there is nothing left to represent the mantissa, and so the X - Floor(X) becomes zero, which is a mantissa of exactly 1.

Can you use bigdecimals for this your logarithm approach? Are we going to get all correct answer without loss in precision?

If BigDecimals (or BigNumbers or BigMath?) has a Logarithm function, then it should work. But given that your example involves numbers with about 446,436,360,569,697,306 decimal digits = 1,483,029,500,000,000,000 bits = 185,378,690,000,000,000 bytes = 168,601 TB then I expect there's going to be a loss of precision. Or to put that number in perspective: to transmit it across a 10 Gbps network link would take more than 5 years.

I don't see how you (or anybody) could get an exactly correct answer, accurate down to the very last digit, with current technology.
 
Upvote 0

emexes

Expert
Licensed User
Longtime User
while the exponent is correct, but I can't still rely on such answer because this difference is still huge

Bear in mind that even if you calculate an answer accurate to a million significant digits, the remaining 446,436,360,568,697,306 digits will be randomlike gibberish (unless the base is a multiple of 10, perhaps, in which case the second half of the remaining digits would be 0).

Also, for your example with base = 3, then we know the recursive sum of the digits of the answer will be a multiple of 3. I have a feeling that the intermediate sums might even be multiples of 9, 27, 81, 243 etc, so maybe that's a useful way to check that the answer is plausibly correct (ie not incorrect). But only for base 3 and multiples of 3.
 
Last edited:
Upvote 0

omo

Active Member
Licensed User
Longtime User
Bear in mind that even if you calculate an answer accurate to a million significant digits, the remaining 446,436,360,568,697,306 digits will be randomlike gibberish.
I got your message perfectly and I remember bignumber library really has no log, the logarithm approach also don't lag unlike bignumber library in the forum that hangs once the digits is more than 6digits and forces app to restart, though very good in other areas of applications where I used it.

However, I still don't know what @ rwblin java bigmath/Bigdecimal did right that makes it work easily despite deficiency in terms of bit limitations of others. It even works on higher than I posted. The only problem I may have now with the approved solution is if I will be able to do further computation on it considering I had already implemented some using existing bignumber library in the forum.

But I will see how it goes first.
Thank you so much, I have learnt more things from you now
 
Upvote 0

omo

Active Member
Licensed User
Longtime User
I don't really understand. Is this another algorithm you could have used or just a clearification of term usage? If it is an algorithm with a solution, then you can let me see the code. The accuracy I was talking about is not such high as you pointed out above: "...calculate an answer accurate to a million significant digits.."

I just want the answer that will be the same or near the same with most reliable advance calculator or algorithm can give.it doesn't need to be highly accurate to about 100 digits. The @rwblinn solution gives accurate answer that some reliable advance calculators and app give. I also tried digits with more exponent than I earlier posted and got result correct. I will explore it more to see what I can do further with it
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…