Share My Creation Number to e notation

Edited 09042025:
This is not a good solution. read the whole tread
********************************************************************************************************
Maybe someone think this is useful

B4X:
Sub NumberToEnotation(Value As Double, SignFigs As Int) As String
    Dim DecPlaces As Int = SignFigs - 1
    Dim isNeg As Boolean
    Dim e As Int
    Dim res As String

    If Value < 0 Then
        Value = Value * -1
        isNeg = True
    End If
   
    If Value >= 1 Then
        e = Floor(Logarithm(Value,10))
        res = $"${NumberFormat2(Value/Power(10,e),1,DecPlaces,DecPlaces, False)}e+${e}"$
    else if Value = 0 Then
        res = NumberFormat2(0,1,DecPlaces,DecPlaces, False)
    Else If Value < 1 Then
        e = Ceil(Logarithm(1/Value,10))
        res = $"${NumberFormat2(Value*Power(10,e),1,DecPlaces,DecPlaces, False)}E-${e}"$
    End If

    If isNeg Then res = "-" & res

    Return res
End Sub
 
Last edited:

emexes

Expert
Licensed User
I'm a little worried that the Log and Pow functions might come back a tiny bit out, what with e being transcendental, but other than that: looks good!
 

knutf

Active Member
Licensed User
Longtime User
I'm not sure what you mean by "come back a tiny bit out"? What do you think can happen?
 

emexes

Expert
Licensed User
What do you think can happen?

Haven't got B4A set up right now, but this is what happens in B4J:

B4X:
Log( Logarithm(1000, 10) )
Log output:
Waiting for debugger to connect...
Program started.
2.9999999999999996
 

emexes

Expert
Licensed User
B4X:
Log( NumberToEnotation(1, 5) )
Log( NumberToEnotation(10, 5) )
Log( NumberToEnotation(100, 5) )
Log( NumberToEnotation(1000, 5) )
Log( NumberToEnotation(10000, 5) )
Log( NumberToEnotation(100000, 5) )
Log( NumberToEnotation(1000000, 5) )
Log( NumberToEnotation(10000000, 5) )
Log( NumberToEnotation(100000000, 5) )
Log( NumberToEnotation(1000000000, 5) )
Log output:
Waiting for debugger to connect...
Program started.
1.0000e+0
1.0000e+1
1.0000e+2
10.0000e+2
1.0000e+4
1.0000e+5
10.0000e+5
1.0000e+7
1.0000e+8
10.0000e+8
 

emexes

Expert
Licensed User
But I still like the concept. Was just using same specific significance precision format a few days ago, for polynomial coefficients when copying trend line equation from spreadsheet into a BASIC program. 🍻

I needed a way to describe this path of a car taking a right turn along this blue line, to calculate the maximum speed possible whilst keeping tyre-to-road forces at a "safe and comfortable" limit:

CurvePath.jpg
 
Last edited:

knutf

Active Member
Licensed User
Longtime User
B4X:
Log( NumberToEnotation(1, 5) )
Log( NumberToEnotation(10, 5) )
Log( NumberToEnotation(100, 5) )
Log( NumberToEnotation(1000, 5) )
Log( NumberToEnotation(10000, 5) )
Log( NumberToEnotation(100000, 5) )
Log( NumberToEnotation(1000000, 5) )
Log( NumberToEnotation(10000000, 5) )
Log( NumberToEnotation(100000000, 5) )
Log( NumberToEnotation(1000000000, 5) )
Log output:
Waiting for debugger to connect...
Program started.
1.0000e+0
1.0000e+1
1.0000e+2
10.0000e+2
1.0000e+4
1.0000e+5
10.0000e+5
1.0000e+7
1.0000e+8
10.0000e+8
I agree, this is ugly. I have to rethink this. Do anyone know another solution?
 

emexes

Expert
Licensed User
Do anyone know another solution?

It's an interesting challenge. I've just assumed that the scientific notation of spreadsheets works correctly.

My first approach would be:
for numbers < 0.1, keep multiplying by 10 until reaches >= 0.1
for numbers >= 1, keep dividig by 10 until reaches < 1
but each of those divisions is going to lose a tiny bit of precision, so... 🤔

anyway, once reach a value between 0.1 (inclusive) and 1 (exclusive) then it's pretty easy

except there will be some edge cases where the mantissa is like 0.999996789 which, if you round it off to 5 decimal places, becomes 1.00000. But you could check the rounded-off string representation, and if it begins with 1. then either make it 0.99999 with the e number the same, or make it 0.10000 with the e number + 1

Maybe. 🤣

Nothing with computer floating point math is ever as easy as it looks. :rolleyes:
 

knutf

Active Member
Licensed User
Longtime User
Thank you Emexes to point out the weakness of my solution. I'll not try to reinvent the wheel. I'll use java formatting as shown below. It works in both B4J and B4A:

B4X:
Sub NumberToEnotation(value As Double,SignFigs As Int) As String
    Dim Formatr As JavaObject
    Formatr.InitializeStatic("java.lang.String")
    
    Dim formatstr As String = $"%.${SignFigs-1}e"$
    Dim Val(1) As Object 'value argument must be in a Object array
    Val(0) = value
    
    Dim res As String = Formatr.RunMethod("format",Array(formatstr,Val))
    Return res
End Sub
 

emexes

Expert
Licensed User
weakness of my solution

Lol only spotted because I might have already walked similar paths and trod in more than one pile of poo myself. So you're not alone. Great minds sink think alike!

The other classic trap with binary (computer) floating point numbers is that decimal fractions are not exact.

Which I found out when a customer showed me an invoice that our system had printed that was clearly wrong.

Something like he was selling 5 washers at 1.1 cents each, which clear-as-day should multiply to 5.5 cents and round off to 6 cents.

But our invoice showed 5 cents.

Nobody was fussed about the 1 cent, but in accounting software: if there's an error, there's an error. Who's to say that whatever's causing that, isn't causing other errors too.

Our solution was to round off using 0.501 rather than 0.5 eg

B4X:
Dim RoundedTotal As Double = Floor(Total * 100 + 0.501) / 100

I remember testing it, and the result was that any number between about (can't remember exactly) 0.5005 and 0.5025 would work for all plausible invoice amounts.
 
Top