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 =...
I already pointed out I did that but couldn't get solution. See here in my text: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"
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))
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).
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).
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")
3 9.35687429879865E+17
.477121254719662 4.46436360569697E+17
.375 4.46436360569697E+17
2.37137370566166 E 4.46436360569697E+17
2.37137370566166 E 446436360569697305.000
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 lostB4X: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.
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.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.
BigNumbers library
If you need to do very accurate claculations using decimal numbers then the normal Java numeric types are not appropriate because, being finite length binary numbers, they cannot accurately represent every possible decimal number. The Java libraries contain a BigDecimal class that is optimised...www.b4x.com
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.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:
View attachment 166387
#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
Me.as(JavaObject).RunMethod("power",Array("3","935687429879864897"))
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
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.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 likeB4X:Me.as(JavaObject).RunMethod("power",Array("3","935687429879864897"))
Thank you, I will try it and get back; but I already seen hope and solution in it.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 with 12 digits: ${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
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.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
the reason why I was getting 1E at the mantissa while exponent was always correct. So, it was due to precision lost
Can you use bigdecimals for this your logarithm approach? Are we going to get all correct answer without loss in precision?
while the exponent is correct, but I can't still rely on such answer because this difference is still huge
recursive sum of the digits
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.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 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.."Apparently the correct name for this is digital root which would not have been my first guess at the definition of that term
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?