How to derive a value from a infinite number in Swift? - ios

My function below will occasionally produce an infinite number. I had thought that I could use my rounding function below to avoid using the infinite number...in other words 1.333333333333(INF) rounded to 1.33, however the compiler still treats the result of the INF.rounded as infinite, how can I round so that I can still put out a value here? Speficially I'm trying to encode to JSON and getting this error:
metadata ERROR = invalidValue(inf, Swift.EncodingError.Context(codingPath: [Watch_Extension.HockeyTrackerMetadata.(CodingKeys in _B2A7010AF20490DAF638D1E0A01E4982).maximumCapableSpeed], debugDescription: "Unable to encode Double.infinity directly in JSON. Use JSONEncoder.NonConformingFloatEncodingStrategy.convertToString to specify how the value should be encoded.", underlyingError: nil))
//Calculation
func calculateMaximumAndAverageSkatingEfficiency() {
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
let heartRatesAsDouble = heartRateValues.map { $0.quantity.doubleValue(for: heartRateUnit)}
let maxHeartRate = heartRatesAsDouble.max()
guard let maxHeartRateUnwrapped = maxHeartRate else { return }
maximumEfficiencyFactor = ((1760.0 * (maxSpeed / 60)) / maxHeartRateUnwrapped).round(to: 2)
guard let averageIceTimeHeartRateUnwrapped = averageIceTimeHeartRate else { return }
averageEfficiencyFactor = ((1760.0 * (averageSpeed / 60)) / averageIceTimeHeartRateUnwrapped).round(to: 2)
}
//Round extension I am using
extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return Darwin.round(self * divisor) / divisor
}
}
//Usage
if let averageEfficiencyFactorUnwrapped = averageEfficiencyFactor {
metadata.averageEfficiencyFactor = averageEfficiencyFactorUnwrapped.round(to: 2)
}

"Infinite value" means that the value is positive or negative infinity, probably because it was the result of a division by zero or a similar mathematical operation. It does not mean that the value is a non-terminating decimal.
Make sure that maxHeartRateUnwrapped and averageIceTimeHeartRateUnwrapped are not zero.

Related

Find the Missing no from an array the efficient way

I am trying to find an efficient way to solve the find a missing number from an array. I implemented the following way it's O(n). Please write any codes that efficiently solves this, just for learning purpose.
func findMissingNo(arrA: [Int]) -> [Int] {
let firstIndex = arrA.first ?? 0
let lastIndex = arrA.last ?? 0
let rslt = Array(firstIndex...lastIndex)
let missingNoArray = rslt.filter{ !arrA.contains($0)}
return missingNoArray
}
findMissingNo(arrA: [11,12,14,15,16,18]) // Prints [13, 17] by looping 9 times
Quickly written and tested (in terms of times performances against your code, but not in term of possible edges cases/mistakes, for instance, if array is 0...10, it won't work, but I'll let you work on the edges cases, since I focused mainly on the main cases, cases which might be covered during an edit and the end of the question)
Your current code:
func findMissingNo(arrA: [Int]) -> [Int] {
let firstIndex = arrA.first ?? 0
let lastIndex = arrA.last ?? 0
let rslt = Array(firstIndex...lastIndex)
let missingNoArray = rslt.filter{ !arrA.contains($0)}
return missingNoArray
}
let numberArray = [11,12,14,15,18]
let missing1 = findMissingNo(arrA: numberArray)
print("Missing1: \(missing1)")
My attempt:
func findMissingNo2(arrA: [Int]) -> [Int] {
var missingNumbers: [Int] = []
guard arrA.count > 2 else { return missingNumbers }
for i in 0...arrA.count-2 {
var current = arrA[i]
let next = arrA[i+1]
if next != current + 1 {
current += 1
while current != next {
missingNumbers.append(current)
current += 1
}
}
}
return missingNumbers
}
let missing2 = findMissingNo2(arrA: numberArray)
print("Missing1: \(missing2)")
Creating a big batch:
var array = Array(0...1000)
for _ in 0...10 {
if let index = array.indices.randomElement() {
let value = array.remove(at: index)
print("removed: \(value)") //To check just in case that's the good value returned by the methods
}
}
Testing:
let date1 = Date()
for _ in 0...100 {
let missing = findMissingNo(arrA: array)
print(missing)
}
print(Date().timeIntervalSince(date1)) //18.617565035820007
let date2 = Date()
for _ in 0...100 {
let missing = findMissingNo2(arrA: array)
print(missing)
}
print(Date().timeIntervalSince(date2)) //0.09566605091094971
print("---End")
print("")
For the time, I got: 18.857954025268555 vs 0.09159696102142334, a big factor difference (~200 times).
Why is there such a big difference?
Because of
let missingNoArray = rslt.filter{ !arrA.contains($0)}
It means:
for each number in result, check if arrayA contains that number.
->
for each number in result, for each number in arrayA (with a stop condition, so it's not a full iteration, but "almost" in term of complexity) check if there is a match...
Here there is a "double" (which is in fact not double, but n?) iteration that you missed.
I tested first with bigger value (array from "0 to 100000"), but it was taking too much time, with that "low number of values", the difference can already be seen.
Instead, you could use a Set:
let missingNoArray = Array(Set(rslt).subtracting(Set(arrA))).sorted()
It's faster than you method in my tests, (double my solution (0.21 ~ 0.22) in time performances), but still much faster than yours.
I added the sorted(), which may or may not be important in your solution, but will add time consumption since Set aren't ordered.
For the edges cases (ie: [3], [3, 4], [3, 8])
guard arrA.count > 2 else { return missingNumbers }
==>
guard !arrA.isEmpty else { return [] }
guard arrA.count > 2 else {
if arrA[0] + 1 >= arrA[1] {
return []
} else {
return Array((arrA[0] + 1)...arrA[1]).dropLast() //Because last will be arrA[1] which is present)
}
}

Firebase iOS -Cast StorageUploadTask Progress From Double to Int

I'm uploading a video file to Firebase Storage and I'm using a progress Indicator to show it's progress. Everything works except I can't get it to display Ints (whole numbers), it's displaying Doubles like:
The numbers should be whole numbers like 0%, 33%, and 96%
I tried casting the percentLabel of type Double to Int but it kept crashing:
let percentComplete: Double = 100.0 * Double(completedUnitCount) / Double(totalUnitCount)
self?.progressLabel.text = "\(Int(percentComplete))%"
How can I get these Doubles to become Ints?
var uploadTask: StorageUploadTask?
uploadTask = videoIdRef?.putFile(from: videoUrl)
uploadTask?.observe(.progress, handler: {
[weak self] (snapshot) in
if let completedUnitCount = snapshot.progress?.completedUnitCount, let totalUnitCount =
snapshot.progress?.totalUnitCount {
let uploadProgress:Float = Float(completedUnitCount) / Float(totalUnitCount)
self?.progressView.progress = uploadProgress
let percentComplete = 100.0 * Double(completedUnitCount) / Double(totalUnitCount)
self?.progressLabel.text = "\(percentComplete)%"
}
})
You could use simple String initializer for this
String(format: "%.0f", floor(percentComplete))

Rounding an Infinite Number?

This question is related to an earlier question however I am receiving an infinite number not related to a divided by 0 problem. For example, the code below prints 4.5300000000000002 in the console but is flagged as .isInfinate and therefore I cannot store using Codable. How can I derive 4.53 (as a double) from this example?
//Calculation
func calculateMaximumAndAverageSkatingEfficiency() {
let heartRateUnit:HKUnit = HKUnit(from: "count/min")
let heartRatesAsDouble = heartRateValues.map { $0.quantity.doubleValue(for: heartRateUnit)}
let maxHeartRate = heartRatesAsDouble.max()
guard let maxHeartRateUnwrapped = maxHeartRate else { return }
maximumEfficiencyFactor = ((1760.0 * (maxSpeed / 60)) / maxHeartRateUnwrapped).round(to: 2)
guard let averageIceTimeHeartRateUnwrapped = averageIceTimeHeartRate else { return }
averageEfficiencyFactor = ((1760.0 * (averageSpeed / 60)) / averageIceTimeHeartRateUnwrapped).round(to: 2)
}
//Round extension I am using
extension Double {
func round(to places: Int) -> Double {
let divisor = pow(10.0, Double(places))
return Darwin.round(self * divisor) / divisor
}
}
//Usage
if let averageEfficiencyFactorUnwrapped = averageEfficiencyFactor {
if averageEfficiencyFactorUnwrapped.isFinite {
hockeyTrackerMetadata.averageEfficiencyFactor = averageEfficiencyFactorUnwrapped.round(to: 2)
} else {
print("AEF is infinite")
}
}
Double cannot precisely store 4.53 for the same reason that you cannot precisely write down the value 1/3 in decimal. (See What Every Programming Should Know About Floating-Point Arithmetic if this is unclear to you.)
If you want your rounding to be in decimal rather than binary, then you need to use a decimal type. See Decimal.
Your round(to:) method is incorrect because it assumes "places" are decimal digits. But Double works in binary digits. I believe what you want is this:
extension Double {
func round(toDecimalPlaces places: Int) -> Decimal {
var decimalValue = Decimal(self)
var result = decimalValue
NSDecimalRound(&result, &decimalValue, places, .plain)
return result
}
}
Note that 4.53 is in no way "infinite." It is somewhat less than 5. I don't see anywhere in your code that it should generate an infinite value. I would double-check how you're determining that.

Get CPU usage IOS Swift

I am trying to get overall CPU usage not of a single app. I found some of the resources but they are either written in C or outdated swift. Can anyone help me with this problem? I am trying to conver this https://github.com/beltex/SystemKit/blob/master/SystemKit/System.swift#L12
to swift.
Till now I am able to convert this much
fileprivate func hostCPULoadInfo() -> host_cpu_load_info{
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride;
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT);
var hostInfo = host_cpu_load_info_t.allocate(capacity: 1);
let result = withUnsafeMutablePointer(to: &hostInfo) {$0.withMemoryRebound(to: integer_t.self, capacity: Int(size)){
host_info(mach_host_self(), Int32(HOST_BASIC_INFO), $0, &size)
}
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
#if DEBUG
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)");
}
#endif
return data;
}
public func cpuUsage() -> (system: Double, user: Double, idle : Double, nice: Double){
let load = hostCPULoadInfo();
let usrDiff: Double = Double(load.cpu_ticks.0 - loadPrevious.cpu_ticks.0);
let systDiff = Double(load.cpu_ticks.1 - loadPrevious.cpu_ticks.1);
let idleDiff = Double(load.cpu_ticks.2 - loadPrevious.cpu_ticks.2);
let niceDiff = Double(load.cpu_ticks.3 - loadPrevious.cpu_ticks.3);
let totalTicks = usrDiff + systDiff + idleDiff + niceDiff
print("Total ticks is ", totalTicks);
let sys = systDiff / totalTicks * 100.0
let usr = usrDiff / totalTicks * 100.0
let idle = idleDiff / totalTicks * 100.0
let nice = niceDiff / totalTicks * 100.0
return (sys, usr, idle, nice);
}
But the thing is I am getting an error like this
Error - /Users/administrator/Downloads/Documents/Swift/SystemInfo/RAMInformation.swift: hostCPULoadInfo() - kern_result_t = 5
Does anybody knows what's wrong in the above code? I thing I am doing wrong on conversion of host_statistics.
Can anybody help me?
There are three errors in your code:
The CPU statistics is obtained by calling host_statistics(), not
host_info().
The "flavor" argument must be HOST_CPU_LOAD_INFO, not HOST_BASIC_INFO.
hostInfo contains the pointer to the allocated structure,
so that value must be rebound, not the address of the variable.
Putting it all together:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride / MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
let hostInfo = host_cpu_load_info_t.allocate(capacity: 1)
let result = hostInfo.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
let data = hostInfo.move()
hostInfo.deallocate(capacity: 1)
return data
}
(I changed the return type to an optional so that nil can be returned
in the error case).
Alternatively, use a local variable instead of allocating and releasing
the host_cpu_load_info structure:
func hostCPULoadInfo() -> host_cpu_load_info? {
let HOST_CPU_LOAD_INFO_COUNT = MemoryLayout<host_cpu_load_info>.stride/MemoryLayout<integer_t>.stride
var size = mach_msg_type_number_t(HOST_CPU_LOAD_INFO_COUNT)
var cpuLoadInfo = host_cpu_load_info()
let result = withUnsafeMutablePointer(to: &cpuLoadInfo) {
$0.withMemoryRebound(to: integer_t.self, capacity: HOST_CPU_LOAD_INFO_COUNT) {
host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, $0, &size)
}
}
if result != KERN_SUCCESS{
print("Error - \(#file): \(#function) - kern_result_t = \(result)")
return nil
}
return cpuLoadInfo
}

How to create a String with format?

I need to create a String with format which can convert Int, Int64, Double, etc types into String. Using Objective-C, I can do it by:
NSString *str = [NSString stringWithFormat:#"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE];
How to do same but in Swift?
I think this could help you:
import Foundation
let timeNow = time(nil)
let aStr = String(format: "%#%x", "timeNow in hex: ", timeNow)
print(aStr)
Example result:
timeNow in hex: 5cdc9c8d
nothing special
let str = NSString(format:"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, LONG_VALUE, STRING_VALUE)
let str = "\(INT_VALUE), \(FLOAT_VALUE), \(DOUBLE_VALUE), \(STRING_VALUE)"
Update: I wrote this answer before Swift had String(format:) added to it's API. Use the method given by the top answer.
No NSString required!
String(format: "Value: %3.2f\tResult: %3.2f", arguments: [2.7, 99.8])
or
String(format:"Value: %3.2f\tResult: %3.2f", 2.7, 99.8)
I would argue that both
let str = String(format:"%d, %f, %ld", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE)
and
let str = "\(INT_VALUE), \(FLOAT_VALUE), \(DOUBLE_VALUE)"
are both acceptable since the user asked about formatting and both cases fit what they are asking for:
I need to create a string with format which can convert int, long, double etc. types into string.
Obviously the former allows finer control over the formatting than the latter, but that does not mean the latter is not an acceptable answer.
First read Official documentation for Swift language.
Answer should be
var str = "\(INT_VALUE) , \(FLOAT_VALUE) , \(DOUBLE_VALUE), \(STRING_VALUE)"
println(str)
Here
1) Any floating point value by default double
EX.
var myVal = 5.2 // its double by default;
-> If you want to display floating point value then you need to explicitly define such like a
EX.
var myVal:Float = 5.2 // now its float value;
This is far more clear.
let INT_VALUE=80
let FLOAT_VALUE:Double= 80.9999
let doubleValue=65.0
let DOUBLE_VALUE:Double= 65.56
let STRING_VALUE="Hello"
let str = NSString(format:"%d , %f, %ld, %#", INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, STRING_VALUE);
println(str);
The accepted answer is definitely the best general solution for this (i.e., just use the String(format:_:) method from Foundation) but...
If you are running Swift ≥ 5, you can leverage the new StringInterpolationProtocol protocol to give yourself some very nice syntax sugar for common string formatting use cases in your app.
Here is how the official documentation summarizes this new protocol:
Represents the contents of a string literal with interpolations while it’s being built up.
Some quick examples:
extension String.StringInterpolation {
/// Quick formatting for *floating point* values.
mutating func appendInterpolation(float: Double, decimals: UInt = 2) {
let floatDescription = String(format: "%.\(decimals)f%", float)
appendLiteral(floatDescription)
}
/// Quick formatting for *hexadecimal* values.
mutating func appendInterpolation(hex: Int) {
let hexDescription = String(format: "0x%X", hex)
appendLiteral(hexDescription)
}
/// Quick formatting for *percents*.
mutating func appendInterpolation(percent: Double, decimals: UInt = 2) {
let percentDescription = String(format: "%.\(decimals)f%%", percent * 100)
appendLiteral(percentDescription)
}
/// Formats the *elapsed time* since the specified start time.
mutating func appendInterpolation(timeSince startTime: TimeInterval, decimals: UInt = 2) {
let elapsedTime = CACurrentMediaTime() - startTime
let elapsedTimeDescription = String(format: "%.\(decimals)fs", elapsedTime)
appendLiteral(elapsedTimeDescription)
}
}
which could be used as:
let number = 1.2345
"Float: \(float: number)" // "Float: 1.23"
"Float: \(float: number, decimals: 1)" // "Float: 1.2"
let integer = 255
"Hex: \(hex: integer)" // "Hex: 0xFF"
let rate = 0.15
"Percent: \(percent: rate)" // "Percent: 15.00%"
"Percent: \(percent: rate, decimals: 0)" // "Percent: 15%"
let startTime = CACurrentMediaTime()
Thread.sleep(forTimeInterval: 2.8)
"∆t was \(timeSince: startTime)" // "∆t was 2.80s"
"∆t was \(timeSince: startTime, decimals: 0)" // "∆t was 3s"
This was introduced by SE-0228, so please be sure to read the original proposal for a deeper understanding of this new feature. Finally, the protocol documentation is helpful as well.
I know a lot's of time has passed since this publish, but I've fallen in a similar situation and create a simples class to simplify my life.
public struct StringMaskFormatter {
public var pattern : String = ""
public var replecementChar : Character = "*"
public var allowNumbers : Bool = true
public var allowText : Bool = false
public init(pattern:String, replecementChar:Character="*", allowNumbers:Bool=true, allowText:Bool=true)
{
self.pattern = pattern
self.replecementChar = replecementChar
self.allowNumbers = allowNumbers
self.allowText = allowText
}
private func prepareString(string:String) -> String {
var charSet : NSCharacterSet!
if allowText && allowNumbers {
charSet = NSCharacterSet.alphanumericCharacterSet().invertedSet
}
else if allowText {
charSet = NSCharacterSet.letterCharacterSet().invertedSet
}
else if allowNumbers {
charSet = NSCharacterSet.decimalDigitCharacterSet().invertedSet
}
let result = string.componentsSeparatedByCharactersInSet(charSet)
return result.joinWithSeparator("")
}
public func createFormattedStringFrom(text:String) -> String
{
var resultString = ""
if text.characters.count > 0 && pattern.characters.count > 0
{
var finalText = ""
var stop = false
let tempString = prepareString(text)
var formatIndex = pattern.startIndex
var tempIndex = tempString.startIndex
while !stop
{
let formattingPatternRange = formatIndex ..< formatIndex.advancedBy(1)
if pattern.substringWithRange(formattingPatternRange) != String(replecementChar) {
finalText = finalText.stringByAppendingString(pattern.substringWithRange(formattingPatternRange))
}
else if tempString.characters.count > 0 {
let pureStringRange = tempIndex ..< tempIndex.advancedBy(1)
finalText = finalText.stringByAppendingString(tempString.substringWithRange(pureStringRange))
tempIndex = tempIndex.advancedBy(1)
}
formatIndex = formatIndex.advancedBy(1)
if formatIndex >= pattern.endIndex || tempIndex >= tempString.endIndex {
stop = true
}
resultString = finalText
}
}
return resultString
}
}
The follow link send to the complete source code:
https://gist.github.com/dedeexe/d9a43894081317e7c418b96d1d081b25
This solution was base on this article:
http://vojtastavik.com/2015/03/29/real-time-formatting-in-uitextfield-swift-basics/
There is a simple solution I learned with "We <3 Swift" if you can't either import Foundation, use round() and/or does not want a String:
var number = 31.726354765
var intNumber = Int(number * 1000.0)
var roundedNumber = Double(intNumber) / 1000.0
result: 31.726
Use this following code:
let intVal=56
let floatval:Double=56.897898
let doubleValue=89.0
let explicitDaouble:Double=89.56
let stringValue:"Hello"
let stringValue="String:\(stringValue) Integer:\(intVal) Float:\(floatval) Double:\(doubleValue) ExplicitDouble:\(explicitDaouble) "
The beauty of String(format:) is that you can save a formatting string and then reuse it later in dozen of places. It also can be localized in this single place. Where as in case of the interpolation approach you must write it again and again.
Simple functionality is not included in Swift, expected because it's included in other languages, can often be quickly coded for reuse. Pro tip for programmers to create a bag of tricks file that contains all this reuse code.
So from my bag of tricks we first need string multiplication for use in indentation.
#inlinable func * (string: String, scalar: Int) -> String {
let array = [String](repeating: string, count: scalar)
return array.joined(separator: "")
}
and then the code to add commas.
extension Int {
#inlinable var withCommas:String {
var i = self
var retValue:[String] = []
while i >= 1000 {
retValue.append(String(format:"%03d",i%1000))
i /= 1000
}
retValue.append("\(i)")
return retValue.reversed().joined(separator: ",")
}
#inlinable func withCommas(_ count:Int = 0) -> String {
let retValue = self.withCommas
let indentation = count - retValue.count
let indent:String = indentation >= 0 ? " " * indentation : ""
return indent + retValue
}
}
I just wrote this last function so I could get the columns to line up.
The #inlinable is great because it takes small functions and reduces their functionality so they run faster.
You can use either the variable version or, to get a fixed column, use the function version. Lengths set less than the needed columns will just expand the field.
Now you have something that is pure Swift and does not rely on some old objective C routine for NSString.
Since String(format: "%s" ...) is crashing at run time, here is code to allow write something like "hello".center(42); "world".alignLeft(42):
extension String {
// note: symbol names match to nim std/strutils lib:
func align (_ boxsz: UInt) -> String {
self.withCString { String(format: "%\(boxsz)s", $0) }
}
func alignLeft (_ boxsz: UInt) -> String {
self.withCString { String(format: "%-\(boxsz)s", $0) }
}
func center (_ boxsz: UInt) -> String {
let n = self.count
guard boxsz > n else { return self }
let padding = boxsz - UInt(n)
let R = padding / 2
guard R > 0 else { return " " + self }
let L = (padding%2 == 0) ? R : (R+1)
return " ".withCString { String(format: "%\(L)s\(self)%\(R)s", $0,$0) }
}
}
Success to try it:
var letters:NSString = "abcdefghijkl"
var strRendom = NSMutableString.stringWithCapacity(strlength)
for var i=0; i<strlength; i++ {
let rndString = Int(arc4random() % 12)
//let strlk = NSString(format: <#NSString#>, <#CVarArg[]#>)
let strlk = NSString(format: "%c", letters.characterAtIndex(rndString))
strRendom.appendString(String(strlk))
}

Resources