I am loading in lines from a text file with very large numbers. String has the toInt method, but how do you convert a string to an Int64 which will be able to handle the large numbers?
I don't see a toInt64 method or a toLong etc. There must be a way, but I haven't found anything by searching yet.
Alternatively I guess I could read the numbers in the string digit by digit (or by groups of digits) and then add them together with appropriate factors of ten, but that seems like overkill. Or maybe the proper way is to read the data in a binary form and convert it that way?
Thanks
As of Swift 2.1.1 you can simply initialize Int64 with String
let number: Int64? = Int64("42")
If you don't mind using NSString, you can do this:
let str = "\(LLONG_MAX)"
let strAsNSString = str as NSString
let value = strAsNSString.longLongValue
Note that unlike toInt(), longLongValue will return 0 if the string is not a legal number whereas toInt() will return nil in that case.
import Darwin
let strBase10 = "9223372036854775807"
let i64FromBase10 = strtoll(strBase10, nil, 10)
let strBase16 = "0xFFFFFFFFFFFFFFFF"
let i64FromBase16 = strtoll(strBase16, nil, 16)
strtoll means STRingTOLongLong
http://www.freebsd.org/cgi/man.cgi?query=strtoll
import Darwin
let str = ...
let i = strtoll(str, nil, 10)
Related
The "GlobalScope" class defines many fundamental enums like the Error enum.
I'm trying to produce meaningful logs when an error occurs. However printing a value of type Error only prints the integer, which is not very helpful.
The Godot documentation on enums indicates that looking up the value should work in a dictionary like fashion. However, trying to access Error[error_value] errors with:
The identifier "Error" isn't declared in the current scope.
How can I convert such enum values to string?
In the documentation you referenced, it explains that enums basically just create a bunch of constants:
enum {TILE_BRICK, TILE_FLOOR, TILE_SPIKE, TILE_TELEPORT}
# Is the same as:
const TILE_BRICK = 0
const TILE_FLOOR = 1
const TILE_SPIKE = 2
const TILE_TELEPORT = 3
However, the names of the identifiers of these constants only exist to make it easier for humans to read the code. They are replaced on runtime with something the machine can use, and are inaccessible later. If I want to print an identifier's name, I have to do so manually:
# Manually print TILE_FLOOR's name as a string, then its value.
print("The value of TILE_FLOOR is ", TILE_FLOOR)
So if your goal is to have descriptive error output, you should do so in a similar way, perhaps like so:
if unexpected_bug_found:
# Manually print the error description, then actually return the value.
print("ERR_BUG: There was a unexpected bug!")
return ERR_BUG
Now the relationship with dictionaries is that dictionaries can be made to act like enumerations, not the other way around. Enumerations are limited to be a list of identifiers with integer assignments, which dictionaries can do too. But they can also do other cool things, like have identifiers that are strings, which I believe you may have been thinking of:
const MyDict = {
NORMAL_KEY = 0,
'STRING_KEY' : 1, # uses a colon instead of equals sign
}
func _ready():
print("MyDict.NORMAL_KEY is ", MyDict.NORMAL_KEY) # valid
print("MyDict.STRING_KEY is ", MyDict.STRING_KEY) # valid
print("MyDict[NORMAL_KEY] is ", MyDict[NORMAL_KEY]) # INVALID
print("MyDict['STRING_KEY'] is ", MyDict['STRING_KEY']) # valid
# Dictionary['KEY'] only works if the key is a string.
This is useful in its own way, but even in this scenario, we assume to already have the string matching the identifier name explicitly in hand, meaning we may as well print that string manually as in the first example.
The naive approach I done for me, in a Singleton (in fact in a file that contain a lot of static funcs, referenced by a class_name)
static func get_error(global_error_constant:int) -> String:
var info := Engine.get_version_info()
var version := "%s.%s" % [info.major, info.minor]
var default := ["OK","FAILED","ERR_UNAVAILABLE","ERR_UNCONFIGURED","ERR_UNAUTHORIZED","ERR_PARAMETER_RANGE_ERROR","ERR_OUT_OF_MEMORY","ERR_FILE_NOT_FOUND","ERR_FILE_BAD_DRIVE","ERR_FILE_BAD_PATH","ERR_FILE_NO_PERMISSION","ERR_FILE_ALREADY_IN_USE","ERR_FILE_CANT_OPEN","ERR_FILE_CANT_WRITE","ERR_FILE_CANT_READ","ERR_FILE_UNRECOGNIZED","ERR_FILE_CORRUPT","ERR_FILE_MISSING_DEPENDENCIES","ERR_FILE_EOF","ERR_CANT_OPEN","ERR_CANT_CREATE","ERR_QUERY_FAILED","ERR_ALREADY_IN_USE","ERR_LOCKED","ERR_TIMEOUT","ERR_CANT_CONNECT","ERR_CANT_RESOLVE","ERR_CONNECTION_ERROR","ERR_CANT_ACQUIRE_RESOURCE","ERR_CANT_FORK","ERR_INVALID_DATA","ERR_INVALID_PARAMETER","ERR_ALREADY_EXISTS","ERR_DOES_NOT_EXIST","ERR_DATABASE_CANT_READ","ERR_DATABASE_CANT_WRITE","ERR_COMPILATION_FAILED","ERR_METHOD_NOT_FOUND","ERR_LINK_FAILED","ERR_SCRIPT_FAILED","ERR_CYCLIC_LINK","ERR_INVALID_DECLARATION","ERR_DUPLICATE_SYMBOL","ERR_PARSE_ERROR","ERR_BUSY","ERR_SKIP","ERR_HELP","ERR_BUG","ERR_PRINTER_ON_FIR"]
match version:
"3.4":
return default[global_error_constant]
# Regexp to use on #GlobalScope documentation
# \s+=\s+.+ replace by nothing
# (\w+)\s+ replace by "$1", (with quotes and comma)
printerr("you must check and add %s version in get_error()" % version)
return default[global_error_constant]
So print(MyClass.get_error(err)), or assert(!err, MyClass.get_error(err)) is handy
For non globals I made this, though it was not your question, it is highly related.
It would be useful to be able to access to #GlobalScope and #GDScript, maybe due a memory cost ?
static func get_enum_flags(_class:String, _enum:String, flags:int) -> PoolStringArray:
var ret := PoolStringArray()
var enum_flags := ClassDB.class_get_enum_constants(_class, _enum)
for i in enum_flags.size():
if (1 << i) & flags:
ret.append(enum_flags[i])
return ret
static func get_constant_or_enum(_class:String, number:int, _enum:="") -> String:
if _enum:
return ClassDB.class_get_enum_constants(_class, _enum)[number]
return ClassDB.class_get_integer_constant_list(_class)[number]
I want to calculate a string, which I'm doing by this:
NSExpression *expression = [NSExpression expressionWithFormat:calculationString];
float result = [[expression expressionValueWithObject:nil context:nil] floatValue];
NSLog(#"%f", result);
The problem is, when calculationstring is 1/2, the result is 0. I tried to change float with double and NSNumber and the %f to %f and %#, but I always just get 0. What to I have to change?
Also if it matters, I am in Europe, so I have commas instead of points for this value, but it shouldn't matter as I am logging with %f which shows it as points. Just for information
Basically, you just need to tell it that you are performing floating point operation,
1.0/2
1.0/2.0
1/2.0
Will all work
Typing in NSExpression is much like in C: literals that look like integers (no decimal point/comma) are treated as integers and thus use integer division. (Under integer division, 1/2 is zero. If you want 0.5, you need floating point division.) This happens when the expression is parsed and evaluated, so attempting to change the type of the result or the formatting of the output has no effect -- those things happen after parsing and evaluation.
If your calculationString is entirely under your control, it's easy to make sure that you use floating point literals anywhere you want floating point division. (That is, use 1.0/2 instead of 1/2.) If not, you'll need to change it such that it does -- here it's probably better to decompose the parsed NSExpression and change an operand rather than munge the string.
Followup edit on the "decompose" bit: String munging in content that you know to have higher-order structure is generally problematic. And with NSExpression, you already have a parser (who's smarter than a simple regex) decomposing the string for you — that is in fact what NSExpression is all about.
So, if you're working with a user-provided string, don't try to change the expression by changing the string. Let NSExpression parse it, then use properties of the resulting object to pick it apart into its constituent expressions. If your string is simply "1/2", then your expression has an array of two arguments and the function "divide:by:" — you can replace it with an equivalent function where one of the arguments is explicitly a floating-point value:
extension NSExpression {
var floatifiedForDivisionIfNeeded: NSExpression {
if function == "divide:by:", let args = arguments, let last = args.last,
let firstValue = args.first?.constantValue as? NSNumber {
let newFirst = NSExpression(forConstantValue: firstValue.doubleValue)
return NSExpression(forFunction: function, arguments: [newFirst, last])
} else {
return self
}
}
}
I think You need to User DDMathParser Which is best in this situation. I have used it in One of my project which is facing same problem as you have faced
DDMathEvaluator *eval = [DDMathEvaluator defaultMathEvaluator];
id value=[eval evaluateString:#"1/2" withSubstitutions:nil error:&error];
NSLog(#"Result %#",value);
Result 0.5
Rickster's solution worked, but had problems with expressions like 5*5/2, where the first argument (here 5*5) was not just a number.
I found a different solution here that works for me: https://stackoverflow.com/a/46554342/6385925
for people who still have this problem i did a somewhat quick fix:
extension String {
var mathExpression: String {
var returnValue = ""
for value in newString.components(separatedBy: " ") {
if value.isOperator {
returnValue += value
} else {
returnValue += "\(Double(value) ?? 0)"
}
}
return returnValue
}
var isOperator: Bool {
["+", "-", "/", "x", "*"].contains(self)
}
}
I am creating an application with separate posts in it (similar to Instagram). Each post is a dictionary located in one big array. Within each dictionary their is an NSDate which I would like to sort the dictionaries by in order from newest to oldest.
I have read similar questions but they are in objective C. I have a feeling NSSortDescriptor be a helpful method but am unsure on how to use it in this situation.
Any help would be great,
Thanks
If you’re writing in Swift, you’ll probably find it easier to use the Swift array type ([ContainedType]) than NSArray. Amongst other things, sorting Swift arrays is more straightforward than having to use NSSortDescriptor etc.
NSDates can be compared using .compare like so:
let d1 = NSDate()
let d2 = NSDate()
d1.compare(d2) == .OrderedAscending
But you might prefer them to implement the Comparable protocol, which can be done like this:
extension NSDate: Comparable { }
public func ==(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.isEqualToDate(rhs)
}
public func <(lhs: NSDate, rhs: NSDate) -> Bool {
return lhs.compare(rhs) == .OrderedAscending
}
// now you can do
d1 > d2
d1 <= d2 //etc
With this, you can sort arrays of dates:
let arr = [d2, d1]
let sortedArr = arr.sorted(<) // or > for descending order
If you had dictionaries of dates, you would need to fetch the date value out dictionary and compare it, but that’s easy:
let dicts = [["Date":d2], ["Date":d1]]
// pass sorted a function that compares two candidates in the array
dicts.sorted { lhs, rhs in
// even though dictionary lookups return optionals,
// this is fine because < is defined for optionals of Comparables
// (nil is < anything else)
lhs["Date"] < (rhs["Date"]
}
Except… chances aren’t that you actually have an array of [String:NSDate] – you probably have a bunch of different types in there and its actually a [String:AnyObject], so you need to convert the type:
// dictionaries contain various different kind of values
let dicts: [[String:AnyObject]] = [["Date":d2], ["Date":d1]]
dicts.sorted { lhs, rhs in
(lhs["Date"] as? NSDate) < (rhs["Date"] as? NSDate)
}
But that said, you probably at this point want to think about storing your data not as a dictionary of stuff, but as a proper data structure:
struct Post {
let timestamp: NSDate
// and various other properties...
}
let posts: [Post] = [
Post(timestamp: d1),
Post(timestamp: d2)
]
posts.sorted { $0.timestamp < $1.timestamp }
EDIT: your comment mentions that you actually have a dictionary of type [String:String]. This means you need to convert the strings to dates somehow before comparing them. In which case, you could use NSDateFormatter to convert as part of the comparison. Some example code:
let dicts: [[String:String]] = [["Date":"May 20 20015"], ["Date":"May 20 2014"]]
let fmt = NSDateFormatter()
fmt.dateStyle = .MediumStyle
let sortedDicts = dicts.sorted { lhs, rhs in
lhs["Date"].flatMap(fmt.dateFromString) < rhs["Date"].flatMap(fmt.dateFromString)
}
So, when doing the comparison, fetch the date string out, then convert it to a NSDate using the formatter, then compare the result.
Note, this uses flatMap – this is because dateFromString itself returns an optional, and you don’t want an optional-optional so you need to flatten the result.
The big downside to this is there’s no detection of invalid dates. If you got a date in there that was a bad format (say, month and day in the wrong order), dateFromString would return nil and it’d get sorted towards the start of the array.
The other downside of this is it’s getting pretty horribly inefficient. You may well be better off converting your data to more structured form (e.g. a struct with an NSDate-typed member variable) before doing this kind of processing.
I have a class that contains a ints, string and pointers to other classes. I'm trying to extract the strings and perform a substring operation on them before I select.Distinct. My LINQ code looks right
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select(kw).Distinct()).ToList();
I have also tried
var crop = …
List<string> crops = crop.ToList();
When I attempt to compile, I'm getting
Cannot implicitly convert type
System.Collections.Generic.List<System.Collections.Generic.IEnumerable<char>> to System.Collections.Generic.List<System.Collections.Generic.IEnumerable<string>>
on the ToList() line.
m.CropName is definitely a string
Why does the compiler think that I'm using a char list rather than a string list and how do I fix this.
Nothing like a simple problem to stump you at the start of a day!
try
List<string> crops = (from m in cropTypes
let cw = m.CropName
let kw = cw.Substring(0, cw.LastIndexOf(")") + 1)
select kw).Distinct().ToList();
If you call Distinct on a string, you're actually enumerating the string's characters.
I am a noob to VB and I need to know how its done.
Haven't done VB in 3 years cannot remember much of it.
The textbox has a value in it (5.43), and it needs to be decreased by 0.34.
But this is the code:
TextBox3.Text = Val(TextBox3.Text) -0.34
How do I do this?
THIS IS VB 6 by the way
TextBox3.Text = CDbl(TextBox3.Text) - 0.34
Because your initial value has parenthesis (5.34) you must convert it to a specific number before operating on in.
Val does not recognize values in parens being negative. The Val() function in your original example is converting it to 0 in the same way that val("abcd") will also return 0 because it assumes both are strings.
You can test these conditions in the immediate window to quickly see the results.
Haven't tried it, but could be:
TextBox3.Text = Cdbl(TextBox3.Text) -0.34
The following code will do it:
TextBox3.Text = Cstr(CDbl(TextBox3.Text) - 0.34)
But you should be aware what is going on.
The TextBox does not store a double type, it stores a string type. The above code attempts to convert the string to a double, subtract your constant value from it, and convert it back to a string.
You should ask yourself what should happen if the string in the text box is not a valid number. In the above code, Double.Parse() will throw an exception. Double.TryParse() will return whether the conversion was successful.
Or is it impossible to enter a non-number into the text box? In which case, the safety check is unnecessary, though advisable.
You need to ask these questions when doing type conversions, or your program will behave unpredictably when a value is not convertible to the type you expected.
A safer way to decrement it would be:
Const DECREMENT_VALUE As Double = 0.34
Dim isDouble As Boolean
isDouble = IsNumeric(TextBox3.Text)
If isDouble Then
Dim newValue As Double
newValue = CDbl(TextBox3.Text)
newValue = newValue - DECREMENT_VALUE
TextBox3.Text = CStr(newValue)
Else
MsgBox "The Value was not a Double! Could not Decrement!"
End If
Try this.. It might just work
Dim TxtValue as Integer
TxtValue = TextBox3.Text
Since TxtValue is Integer, the decimal will be automatically dropped.
Like this??
TextBox3.Text=Double.Parse(TextBox3.Text)-0.43
This will work in C#
double number = Convert.ToDouble(textBox1.Text);
number = number - .34;