In dart, as I am a newbie using extension, I want to make a simple extension to check value is double.
extension numberExtension on num{
bool get isInteger => (this % 1) == 0;
bool get isDouble =>double.tryParse(this) != null;
}
here isInteger is correct, but for isDouble I get this error:
The argument type 'num' can't be assigned to the parameter type
'String'
Problem is this in isDouble getter!?
Assuming anything that is not an Integer is a Float or a Double;
Why not implement isDecimal instead, something like:
extension numberExtension on num {
bool get isInteger => (this % 1) == 0;
bool get isDecimal => (this % 1) != 0;
}
OR
extension numberExtension on num {
bool get isInteger => this is int;
bool get isDecimal => !(this is int);
}
Note that we could directly use "this is double" above,
but the "!(this is int)" check is simply more change-compatible,
because it would even work if Dart ever adds some new num sub-type.
Update; looking into docs tells us that:
If compiled into JavaScript, there is no real int type, only doubles without decimal.
Dart does not seem to support 32-bit float, but has 64-bit double at least.
int is always 64-bit (just like double), but bitwise and/or shift operators truncate it into 32-bit (losing data or percision).
Replace
double.tryParse(this) != null
with
this is double
Your original approach:
extension numberExtension on num {
bool get isInteger => (this % 1) == 0;
bool get isDouble =>double.tryParse(this) != null;
}
doesn't work because your extension is on num, so this is a num. double.tryParse expects to parse a String.
Why don't you just check if the object is an int or double directly?
extension numberExtension on num {
bool get isInteger => this is int;
bool get isDouble => this is double;
}
Of course, the extension is not very useful since x.isDouble is not much more convenient to use than using x is double directly, and the latter has the benefit of allowing automatic type-promotion to occur.
(Also, for Dart for the web, where int and double types are both backed by JavaScript numbers, numbers can be reported as both int and double, but using heuristics like % 1 and double.tryParse won't help with that.)
Related
Very simple issue. I have the useless class:
class Useless{
double field;
Useless(this.field);
}
I then commit the mortal sin and call new Useless(0);
In checked mode (which is how I run my tests) that blows up, because 'int' is not a subtype of type 'double'.
Now, it works if I use new Useless(0.0) , but honestly I spend a lot of time correcting my tests putting .0s everywhere and I feel pretty dumb doing that.
As a temporary measure I rewrote the constructor as:
class Useless{
double field;
Useless(num input){
field = input.toDouble();
}
}
But that's ugly and I am afraid slow if called often. Is there a better way to do this?
Simply toDouble()
Example:
int intVar = 5;
double doubleVar = intVar.toDouble();
Thanks to #jamesdlin who actually gave this answer in a comment to my previous answer...
In Dart 2.1, integer literals may be directly used where double is expected. (See https://github.com/dart-lang/sdk/issues/34355.)
Note that this is syntactic sugar and applies only to literals. int variables still won't be automatically promoted to double, so code like:
double reciprocal(double d) => 1 / d;
int x = 42;
reciprocal(x);
would fail, and you'd need to do:
reciprocal(x.toDouble());
You can also use:
int x = 15;
double y = x + .0;
use toDouble() method.
For e.g.:
int a = 10
print(a.toDouble)
//or store value in a variable and then use
double convertedValue = a.toDouble()
From this attempt:
class Useless{
double field;
Useless(num input){
field = input.toDouble();
}
}
You can use the parse method of the double class which takes in a string.
class Useless{
double field;
Useless(num input){
field = double.parse(input.toString()); //modified line
}
}
A more compact way of writing the above class using constructor's initialisers is:
class Useless{
double _field;
Useless(double field):_field=double.parse(field.toString());
}
Since all divisions in flutter result to a double, the easiest thing I did to achieve this was just to divide the integer value with 1:
i.e.
int x = 15;
double y = x /1;
There's no better way to do this than the options you included :(
I get bitten by this lots too, for some reason I don't get any warnings in the editor and it just fails at runtime; mighty annoying :(
I'm using a combination:
static double checkDouble(dynamic value) {
if (value is String) {
return double.parse(value);
} else if (value is int) {
return 0.0 + value;
} else {
return value;
}
}
This is how you can cast from int to double
int a = 2;
double b = a*1.0;
Converting a String to Int returns an optional value but converting a Double to Int does not return an optional value. Why is that? I wanted to check if a double value is bigger than maximum Int value, but because converting function does not return an optional value, I am not be able to check by using optional binding.
var stringNumber: String = "555"
var intValue = Int(stringNumber) // returns optional(555)
var doubleNumber: Double = 555
var fromDoubleToInt = Int(doubleNumber) // returns 555
So if I try to convert a double number bigger than maximum Integer, it crashes instead of returning nil.
var doubleNumber: Double = 55555555555555555555
var fromDoubleToInt = Int(doubleNumber) // Crashes here
I know that there's another way to check if a double number is bigger than maximum Integer value, but I'm curious as why it's happening this way.
If we consider that for most doubles, a conversion to Int simply means dropping the decimal part:
let pieInt = Int(3.14159) // 3
Then the only case in which the Int(Double) constructor returns nil is in the case of an overflow.
With strings, converting to Int returns an optional, because generally, strings, such as "Hello world!" cannot be represented as an Int in a way that universally makes sense. So we return nil in the case that the string cannot be represented as an integer. This includes, by the way, values that can be perfectly represented as doubles or floats:
Consider:
let iPi = Int("3.14159")
let dPi = Double("3.14159")
In this case, iPi is nil while dPi is 3.14159. Why? Because "3.14159" doesn't have a valid Int representation.
But meanwhile, when we use the Int constructor which takes a Double and returns non-optional, we get a value.
So, if that constructor is changed to return an optional, why would it return 3 for 3.14159 instead of nil? 3.14159 can't be represented as an integer.
But if you want a method that returns an optional Int, returning nil when the Double would overflow, you can just write that method.
extension Double {
func toInt() -> Int? {
let minInt = Double(Int.min)
let maxInt = Double(Int.max)
guard case minInt ... maxInt = self else {
return nil
}
return Int(self)
}
}
let a = 3.14159.toInt() // returns 3
let b = 555555555555555555555.5.toInt() // returns nil
Failable initializers and methods with Optional return types are designed for scenarios where you, the programmer, can't know whether a parameter value will cause failure, or where verifying that an operation will succeed is equivalent to performing the operation:
let intFromString = Int(someString)
let valueFromDict = dict[someKey]
Parsing an integer from a string requires checking the string for numeric/non-numeric characters, so the check is the same as the work. Likewise, checking a dictionary for the existence of a key is the same as looking up the value for the key.
By contrast, certain operations are things where you, the programmer, need to verify upfront that your parameters or preconditions meet expectations:
let foo = someArray[index]
let bar = UInt32(someUInt64)
let baz: UInt = someUInt - anotherUInt
You can — and in most cases should — test at runtime whether index < someArray.count and someUInt64 < UInt32.max and someUInt > anotherUInt. These assumptions are fundamental to working with those kinds of types. On the one hand, you really want to design around them from the start. On the other, you don't want every bit of math you do to be peppered with Optional unwrapping — that's why we have types whose axioms are stated upfront.
Let's say I do the following in C++:
int i = 1;
int* ptr = &i;
*ptr = 2;
cout << i << '\n';
And I want to do something similar in swift. Could I do the following?
var i : Int = 1
var iptr : UnsafeMutablePointer<Int> = &i
iptr.memory = 2
print(i)
And achieve the same result?
Yes-ish.
You can't do it exactly as you've attempted in the question. It won't compile. Swift won't let you directly access the address of a value like this. At the end of the day, the reason is mostly because there's simply no good reason to do so.
We do see the & operator in Swift however.
First of all, there is the inout keyword when declaring function parameters:
func doubleIfPositive(inout value: Float) -> Bool {
if value > 0 {
value *= 2
return true
}
return false
}
And to call this method, we'd need the & operator:
let weMadeARadian = doubleIfPositive(&pi)
We can see it similarly used when we have a function which takes an argument of type UnsafeMutablePointer (and other variants of these pointer structs). In this specific case, it's primarily for interoperability with C & Objective-C, where we could declare a method as such:
bool doubleIfPositive(float * value) -> bool {
if (value > 0) {
value *= 2;
return true;
}
return false;
}
The Swift interface for that method ends up looking somethin like this:
func doubleIfPositive(value: UnsafeMutablePointer<Float>) -> Bool
And calling this method from Swift actually looks just like it did before when using the inout approach:
let weMadeARadian = doubleIfPositive(&pi)
But these are the only two uses of this & operator I can find in Swift.
With that said, we can write a function that makes use of the second form of passing an argument into a method with the & operator and returns that variable wrapped in an unsafe mutable pointer. It looks like this:
func addressOf<T>(value: UnsafeMutablePointer<T>) -> UnsafeMutablePointer<T> {
return value
}
And it behaves about as you'd expect from your original code snippet:
var i: Int = 1
var iPtr = addressOf(&i)
iPtr.memory = 2
print(i) // prints 2
As noted by Kevin in the comments, we can also directly allocate memory if we want.
var iPtr = UnsafeMutablePointer<Int>.alloc(1)
The argument 1 here is effectively the mount of space to allocate. This says we want to allocate enough memory for a single Int.
This is roughly equivalent to the following C code:
int * iPtr = malloc(1 * sizeof(int));
BUT...
If you're doing any of this for anything other than interoperability with C or Objective-C, you're most likely not Swifting correctly. So before you start running around town with pointers to value types in Swift, please, make sure it's what you absolutely need to be doing. I've been writing Swift since release, and I've never found the need for any of these shenanigans.
Like this (not the only way, but it's clear):
var i : Int = 1
withUnsafeMutablePointer(&i) {
iptr -> () in
iptr.memory = 2
}
print(i)
Not a very interesting example, but it is completely parallel to your pseudo-code, and we really did reach right into the already allocated memory and alter it, which is what you wanted to do.
This sort of thing gets a lot more interesting when what you want to do is something like cycle thru memory just as fast as doing pointer arithmetic in C.
I found the following code compiles and works:
func foo(p:UnsafePointer<UInt8>) {
var p = p
for p; p.memory != 0; p++ {
print(String(format:"%2X", p.memory))
}
}
let str:String = "今日"
foo(str)
This prints E4BB8AE697A5 and that is a valid UTF8 representation of 今日
As far as I know, this is undocumented behavior. from the document:
When a function is declared as taking a UnsafePointer argument, it can accept any of the following:
nil, which is passed as a null pointer
An UnsafePointer, UnsafeMutablePointer, or AutoreleasingUnsafeMutablePointer value, which is converted to UnsafePointer if necessary
An in-out expression whose operand is an lvalue of type Type, which is passed as the address of the lvalue
A [Type] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call
In this case, str is non of them.
Am I missing something?
ADDED:
And it doesn't work if the parameter type is UnsafePointer<UInt16>
func foo(p:UnsafePointer<UInt16>) {
var p = p
for p; p.memory != 0; p++ {
print(String(format:"%4X", p.memory))
}
}
let str:String = "今日"
foo(str)
// ^ 'String' is not convertible to 'UnsafePointer<UInt16>'
Even though the internal String representation is UTF16
let str = "今日"
var p = UnsafePointer<UInt16>(str._core._baseAddress)
for p; p.memory != 0; p++ {
print(String(format:"%4X", p.memory)) // prints 4ECA65E5 which is UTF16 今日
}
This is working because of one of the interoperability changes the Swift team has made since the initial launch - you're right that it looks like it hasn't made it into the documentation yet. String works where an UnsafePointer<UInt8> is required so that you can call C functions that expect a const char * parameter without a lot of extra work.
Look at the C function strlen, defined in "shims.h":
size_t strlen(const char *s);
In Swift it comes through as this:
func strlen(s: UnsafePointer<Int8>) -> UInt
Which can be called with a String with no additional work:
let str = "Hi."
strlen(str)
// 3
Look at the revisions on this answer to see how C-string interop has changed over time: https://stackoverflow.com/a/24438698/59541
I have the following section of code in an app that I am writing:
...
String[] Columns = Regex.Split(CurrentLine, Delimeter);
Nullable<Double> AltFrom;
...
if (AltFrom == null)
{
Double.TryParse(Columns[LatIndex].Trim(), out AltFrom);
}
...
The line in the if clause will not compile and shows the error: cannot convert from 'out double?' to 'out double'
if I don't make AltFrom a Nullable type and rather explicitly state it as a Double, everything is happy.
Surely this is valid code. Is this just a bug in c# or am I doing something wrong?
No the out parameter really needs to be a double, not a Nullable<double>.
double? altFrom = null;
double temp = 0;
if (double.TryParse( Columns[LatIndex].Trim(), out temp))
{
altFrom = temp;
}
First, you can not implicitly convert a double? to a double. The reason is because what would be the value of the double if the double? represented the null value (i.e., value.HasValue is false)? That is, converting from a double? to a double results in a loss of information (it is a narrowing conversion). Implicit narrowing conversions are generally frowned upon in the framework.
But actually, the problem that you are seeing here is something different. When you have a method that accepts an out parameter of type T, you must pass in a variable of type T; there can not be any type variation in this case as there is with non-ref and non-out parameters.
To get around your problem, use the following:
if (AltFrom == null) {
double value;
Double.TryParse(Columns[LatIndex].Trim(), out value);
AltFrom = value;
}