Android Question milliseconds to hours

Scantech

Well-Known Member
Licensed User
B4X:
Sub ConvertMillisecondsToString(t As Long) As String
   Dim hours, minutes, seconds As Int
   hours = t / DateTime.TicksPerHour
   minutes = (t Mod DateTime.TicksPerHour) / DateTime.TicksPerMinute
   seconds = (t Mod DateTime.TicksPerMinute) / DateTime.TicksPerSecond
   Return $"$1.0{hours}:$2.0{minutes}:$2.0{seconds}"$
End Sub
I believe this has its limitation up to 480 hours. Anything beyond will result in error.

B4X:
Log(ConvertMillisecondsToString((864000 * 2) * 1000))
864000 * 1000 = 240 hours. if using (864000 * 3) * 1000 = -473:-02:-47
 

Scantech

Well-Known Member
Licensed User
The Above statement is incorrect
B4X:
    Dim b As Long
    b = ((864000 * 3) * 1000)
    b = 2592000000
    Log(ConvertMillisecondsToString(b))
why is it with b = ((864000 * 3) * 1000) will result error and using b = 2592000000 will result correct value?

They both have same value??
 
Last edited:

Scantech

Well-Known Member
Licensed User
B4X:
    Dim g As Long = 864000
    Dim g2 As Long = 3
    Dim g3 As Long = 1000
    Dim b As Long
    b = ((g * g2) * g3)
    Log(b)
value is 2592000000 which is correct
my assumption is all numeric values must be passed to a variable?? I think it should work the other way around too. Might be a bug??
 

emexes

Well-Known Member
Licensed User
b = ((864000 * 3) * 1000) = -1702967296 ??? according to log
The issue will be that the expression is being calculated using signed 32-bit ints by default, since there is no term within the expression that tells the compiler that a larger numeric type is required.

((864000 * 3) * 1000) = 2592000000 (decimal) = 0b10011010011111101100100000000000 (binary) which has the high bit (bit 31) set which makes it a negative number, since Ints in B4A/B4J/Java are signed 32-bit numbers.
 

emexes

Well-Known Member
Licensed User
Something new i have learned today. :)
Me too. I'm trying to find a way to force expression evaluation to use 64-bit Long rather than 32-bit Int. You can sort-of do it by adding ".0" to constants (or at least the innermost constant) which makes it a Double, but then you are working with 56 bits of precision rather than 63, so that could be an issue for large numbers.

(deleted various ideas, after realising...)

surely those built in constants, like DateTime.TicksPerSecond, are Longs, in which case this should work correctly:
B4X:
Dim b As Long
b = 864000 * 3 * 1000    'calculated using Int operations
Log(b)
b = 864000 * 3 * DateTime.TicksPerSecond    'calculated using Long operations (cast/forced by TicksPerSecond being Long)
Log(b)
 
Last edited:

OliverA

Expert
Licensed User
How much closer could it be
Closer to why it is happening and how to avoid it. One of the numbers on the right side must be a long to force the whole calculation to be long. If you absolutely want to prevent overflows, then make the first number the long, since several int multiplications before the long can still cause an overflow.
 

emexes

Well-Known Member
Licensed User
Closer to why it is happening and how to avoid it. One of the numbers on the right side must be a long to force the whole calculation to be long. If you absolutely want to prevent overflows, then make the first number the long, since several int multiplications before the long can still cause an overflow.
Fair enough :) I'll revise my suggestion to:
B4X:
b = 864000 * (3 * DateTime.TicksPerSecond)
which should be enough to outwit an optimizing compiler that rearranges or folds constant (sub)expressions.
 
Top