I am expecting the code below to cover the full Float range of which I use only a very small part just above 0.
My app however sometimes crashes in the field because it hits default: fatalError().
What could possibly be wrong here?
var value: Float // Between a little above 0 and about 15.
...
switch value
{
case ...3: return 0
case 3...10: return 1
case 10...: return 2
default: fatalError()
}
This switch will fall all the way through default for example if value is Float.nan or Float.signalingNaN, so it's technically possible for the app to legitimately crash at that point.
Consider adding some logging before crashing to check which value causes it to crash.
You have covered all cases except for the values whose eight exponent bits are all 1s. None of these are "Between a little above 0 and about 15", so your assumption is currently incorrect.
https://en.wikipedia.org/wiki/Single-precision_floating-point_format#Exponent_encoding
Related
I have some very simple code that does a calculation and converts the resulting double to an int.
let startingAge = (Double(babyAge/2).rounded().nextDown)
print(startingAge)
for each in 0..<allQuestions.count {
if allQuestions[each] == "\(Int(startingAge))"
The first print of startingAge gives me the correct answer, for example 5.0. But when it converts to an Int, it gives me an answer of 4. When the Double is 6.0, the int is 5.
I'm feeling stupid, but can't figure out what I'm doing wrong.
When you call rounded(), you round your value to the nearest integer.
When you call .nextDown, you get the next possible value less than the existing value, which means you now have the highest value that's less than the nearest integer to your original value. This still displays as the integer when you print it, but that's just rounding; it's really slightly less than the integer. So if it's printing as "4.0", it's really something like 3.9999999999999 or some such.
When you convert the value to an Int, it keeps the integer part and discards the part to the right of the decimal. Since the floating-point value is slightly less than the integer you rounded to thanks to .nextDown, the integer part is going to be one less than that integer.
Solution: Get rid of the .nextDown.
When you cast you lose precession.
In your case the line returns a double: Assume baby age is 9 then startingAge is 3.999999
let startingAge = (Double(babyAge/2).rounded().nextDown)
and when you print it your answer becomes 3
print("\(Int(startingAge))")
To fix this use this line instead:
let startingAge = (Double(babyAge/2).rounded().nextDown).rounded()
This is what nextdown does, it does not round values, and if the number is
a floating point number it becomes slightly less. If the number was to be an int it would become 1 less I presume.
I am not able to understand what is the logic behind these lines:
COMPUTE temp = RESULT - 1.843E19.
IF temp IS LESS THAN 1.0E16 THEN
Data definition:
000330 01 VAR1 COMP-1 VALUE 3.4E38. // 3.4 x 10 ^ 38
Here are those lines in context (the sub-program returns a square root):
MOVE VAR1 TO PARM1.
CALL "SQUAREROOT_ROUTINE" USING
BY REFERENCE PARM1,
BY REFERENCE RESULT.
COMPUTE temp = RESULT - 1.843E19.
IF temp IS LESS THAN 1.0E16 THEN
DISPLAY "OK"
ELSE
DISPLAY "False"
END-IF.
These lines are just trying to test if the result returned by the SQUAREROOT_ROUTINE is correct. Since the program is using float-values and rather large numbers this might look a bit complicated. Let's just do the math:
You start with 3.4E38, the squareroot is 1.84390889...E19.
By subtracting 1.843E19 (i.e. the approximate result) and comparing the difference against 1.0E16 the program is testing whether the result is between 1.843E19 and 1.843E19+1.0E16 = 1.844E19.
Not that this test would not catch an error if the result from SQUAREROOT_ROUTINE was too low instead of too high. To catch both types of wrong results you should compare the absolute value of the difference against the tolerance.
You might ask "Why make things so complicated"? The thing is that float-values usually are not exact and depending on the used precision you will get sightly different results due to rounding-errors.
well the logic itself is very straight forward, you are subtracting 1.843*(10^19) from the result you get from the SQUAREROOT_ROUTINE and putting that value in the variable called temp and then If the value of temp is less than 1.0*(10^16) you are going to print a line out to the SYSOUT that says "OK", otherwise you are going to print out "False" (if the value was equal to or greater than).
If you mean the logic as to why this code exists, you will need to talk to the author of the code, but it looks like a debugging display that was left in the program.
I'm trying to make a path (CGMutablePath) to be used for a shape node in SpriteKit (SKShapeNode). I'm running my code and it stops and says EXC_BREAKPOINT as if there's a breakpoint in the compiler, when there isn't one. Below is a screenshot of what I have.
As you can see, I have no breakpoint set in the compiler. It just tends to stop at line 31. There's nothing in the logs that give a reason for this crash, if there were one to begin with.
I'm used to Objective-C stopping in main.m with Thread 1: SIGABRT and an NSException in the log, but this just makes no sense. Can someone please explain what's wrong?
EDIT: here are more screenshots to prove I have no breakpoints set. When I get an exception, it simply throws a breakpoint.
That exception happens because arc4random() returns UInt32 and you are subtracting a value of that, which possibly causes a negative value, which is not representable as an unsigned integer.
To fix this you may want to cast the expression to Int32 before subtracting:
var y = CGFloat(self.size.height / 3) + CGFloat((Int32)(arc4random() % 100) - 50)
Regarding the x value above - you create CGFloat and only subtract after that and therefore not encounter the above situation. Therefore a different fix would be the following
var y = CGFloat(self.size.height / 3) + CGFloat(arc4random() % 100) - 50
You basically have to ensure that at the point where you subtract something you have no unsigned type present.
The annoying thing about this is that the compiler does not warn you and the code actually works sometimes, every time when arc4random returns something larger than 50 and will therefore not drift into the negative values...
Incorporating the feedback and suggestion that you should not use arc4random % something the best solution would be to use arc4random_uniform.
arc4random % something will not yield a proper distribution of the random values, while arc4random_uniform(something) does - this has already been discussed on SO before.
A final note: you probably should choose 101 as upper bound instead of 100 because both arc4random as well as arc4random_uniform produce a value between 0 and (upper-1), e.g. 0 and 99. If you subtract 50 you get a value between -50 and +49. Choosing 101 will yield the desired range of -50 to +50.
var y = CGFloat(self.size.height / 3) + CGFloat(arc4random_uniform(101)) - 50
Should I return a optional value like:
func someFunc(#num: Int) -> Obj? {
if num < 0 {
return nil
}
...
}
Or just use assert:
func someFunc(#num: Int) -> Obj {
assert(num >= 0, "Number should greater or equal then zero")
...
}
Edit: Now the conditions are identical in two cases, the number should greater or equal then 0. Negative values are not permitted.
If you use assert and the caller passes an invalid argument it is a non-recoverable error/crash. The caller may not be aware of all the ways the assert may be caused, that is internal logic the caller is not supposed to know.
Really the only time assert is meaningful is to check the calling arguments on method entry and even in that case it must be made clear to the user exactly what is invalid and that can never be made more stringent for the life of the method.
Since this is about Swift returning an Optional seems to make the most sense and it will be clear to the caller that a possible error must be handled. Optionals are a major feature of Swift, use them.
Or always return a useful result the way atan() handles being called with ±0 and ±Inf.
It depends on what you want the precondition of the function to be: if it is an error call it with a negative value (or non-positive; your two examples are contradictory), then go with the assert and document this. Then it becomes part of the contract that the user of the function must check the value if it's uncertain. Or if it makes more sense to support these values and return nil (e.g., the function will typically be called with such values and the nil is not an issue for that typical use), do that instead… Without knowing the details it's impossible to tell which suits best, but my guess would be the former.
The Apple documentation says
Every switch statement must be exhaustive. That is, every possible
value of the type being considered must be matched by one of the
switch cases.
So in new Xcode I have placed a code like this
println(UInt16.min); // Output : '0'
println(UInt16.max); // Output : '65535'
var quantity : UInt16 = 10;
switch quantity {
case 0...65535: //OR case UInt16.min...UInt16.max:
println();
default:
println();
}
Now if i remove the default section I get a compiler error:
Switch must be exhaustive
Do you want to add missing cases? Fix
So my question is for a case that I have mentioned as case 0...65535: have I not mentioned all the case values for an UInt16 ?? But still I am getting an error ?? Why am I getting this error, Did i miss something ??
Swift only truly verifies that a switch block is exhaustive when working with enum types. Even a switching on Bool requires a default block in addition to true and false:
var b = true
switch b {
case true: println("true")
case false: println("false")
}
// error: switch must be exhaustive, consider adding a default clause
With an enum, however, the compiler is happy to only look at the two cases:
enum MyBool {
case True
case False
}
var b = MyBool.True
switch b {
case .True: println("true")
case .False: println("false")
}
If you need to include a default block for the compiler's sake but don't have anything for it to do, the break keyword comes in handy:
var b = true
switch b {
case true: println("true")
case false: println("false")
default: break
}
Part of why you see that error because the compiler can't verify that switch is exhaustive without running code. The expression 0...65535 creates a ClosedInterval struct, and when the switch statement executes it has to ask that struct if the value quantity is in the interval. There's room for that to change at run time, so the compiler can't check it at compile time. (See the Halting Problem.)
More generally, the compiler can't detect an exhaustive switch for integer values — even if you add specific cases for every integer value (case 0: ... case 1: ... ... case 65535:), it doesn't know your switch is exhaustive. (Theoretically it could, though: consider filing a feature request about this if it's something you'd like to see.)
As it stands, there are two scenarios where Swift can detect completeness and allow you to omit the default clause: enums and value binding in tuples. #NateCook's answer covers enums — if you switch on an enum value and have a case in your switch for every case in the enum, you don't need a default. You also don't need a default label if you switch on a tuple and bind every possible combination of values, as seen in the Swift book:
switch anotherPoint {
case (let x, 0):
println("on the x-axis with an x value of \(x)")
case (0, let y):
println("on the y-axis with a y value of \(y)")
case let (x, y):
println("somewhere else at (\(x), \(y))")
}
You might generalize this rule as "if the type system knows about the possible values of your type, it can detect switch completeness", but the fact that there's a level on which the type system doesn't know the range of possible (e.g.) UInt32 values is sort of splitting hairs...
Swift 4.1. Either you need to specify all cases or Just include default block inside switch statement.
(As of Swift 4.2, and probably earlier): I have a helper function that converts a Bool? into the selectedSegmentIndex for a UISegmentedControl with 2 segments. If the value is nil then neither segment should be selected. My function uses a switch, which returns the appropriate segment index for true or false values, and uses this to explicitly test for the nil and satisfy the compiler's need for it to be exhaustive:
case nil: // only remaining possible value
fallthrough
default:
return UISegmentedControl.noSegment
Technically, the case nil: fallthrough isn't required because the default: will suffice, but this syntax may be useful if you want to explicitly test a value to make the code more self-documenting, or perhaps in another situation.
Check if your enum was initialised as an optional which could be either case or nil