Android Question milliseconds to hours

Discussion in 'Android Questions' started by Scantech, Jul 30, 2019.

  1. Scantech

    Scantech Well-Known Member Licensed User

    Code:
    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.

    Code:
    Log(ConvertMillisecondsToString((864000 * 2) * 1000))
     
  2. Scantech

    Scantech Well-Known Member Licensed User

    The Above statement is incorrect
    Code:
    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: Jul 30, 2019
  3. Scantech

    Scantech Well-Known Member Licensed User

     
  4. Scantech

    Scantech Well-Known Member Licensed User

    Code:
    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)
    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??
     
  5. emexes

    emexes Well-Known Member Licensed User

    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.
     
    Shelby and Scantech like this.
  6. emexes

    emexes Well-Known Member Licensed User

    More of a trap than a bug, similar to the limited precision of Floats, or that binary floating point can't represent decimal fractions.

    Most languages do the same overflow-to-negative mod-2^31 arithmetic thing, unless you turn on runtime checking.
     
    Shelby and Scantech like this.
  7. Scantech

    Scantech Well-Known Member Licensed User

    Well thanks for your input. Something new i have learned today. :)
     
  8. emexes

    emexes Well-Known Member Licensed User

    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:
    Code:
    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: Jul 30, 2019
    Shelby likes this.
  9. OliverA

    OliverA Expert Licensed User

  10. emexes

    emexes Well-Known Member Licensed User

    How much closer could it be, given that it calculates the correct answer?

    :)
     
    Last edited: Jul 30, 2019
    Shelby likes this.
  11. OliverA

    OliverA Expert 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.
     
  12. emexes

    emexes Well-Known Member Licensed User

    Fair enough :) I'll revise my suggestion to:
    Code:
    b = 864000 * (3 * DateTime.TicksPerSecond)
    which should be enough to outwit an optimizing compiler that rearranges or folds constant (sub)expressions.
     
    Shelby and OliverA like this.
Loading...
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice