In the code below, I declared a variable by adding up different values depending on if some Toggles are true or false. When I try and print this variable it returns with a number and a single decimal after but it then is followed by a lot of 0 after it. Is there a way to display no zeros after the number?
Disclaimer I am using Swift Playground
var rvalues = [6.5, 5.9, 5.3, 4.8, 4.2, 3.5, 3.1, 2.9, 1.75, 1.5, 1.2, 1.05, 0.92, 0.82, 0.75, 0.7]
var r0 : Double {
model.rvalues[(model.wearingMaskToggle ? 1:0) + (model.washingHandsToggle ? 2:0) + (model.quarantineToggle ? 8:0) + (model.coverMouthToggle ? 4:0)]
}
First, if you are curious where those 0 come from, read is floating point math broken? - a lot of the values in your array aren't precisely representable as Doubles.
To solve your display problem, use a NumberFormatter with minimumFractionDigits and maximumFractionDigits set appropriately.
Alternatively, use Decimal to represent your values.
Related
This question already has an answer here:
How to store 1.66 in NSDecimalNumber
(1 answer)
Closed 5 years ago.
I've read a lot that NSDecimalNumber is the best format to use when using currency.
However, I'm still getting floating point issues.
For example.
let a: NSDecimalNumber = 0.07 //0.07000000000000003
let b: NSDecimalNumber = 7.dividing(by: 100) //0.06999999999999999
I know I could use Decimal and b would be what I'm expecting:
let b: Decimal = 7 / 100 //0.07
I'm using Core Data in my app. So I'm stuck with NSDecimalNumber. Unless I want convert a lot of NSDecimalNumbers to Decimals.
Can someone help me get 0.07?
The problem is that you’re effectively doing floating point math (with the problems it has faithfully capturing fractional decimal values in a Double) and creating a Decimal (or NSDecimalNumber) from the Double value that already has introduced this discrepancy. Instead, you want to create your Decimal values before doing your division (or before having a fractional Double value, even if a literal).
So, the following is equivalent to your example, whereby it is building a Double representation (with the limitations that entails) of 0.07, and you end up with a value that is not exactly 0.07:
let value = Decimal(7.0 / 100.0) // or NSDecimalNumber(value: 7.0 / 100.0)
Whereas this does not suffer this problem because we are dividing a decimal 7 by a decimal 100:
let value = Decimal(7) / Decimal(100) // or NSDecimalNumber(value: 7).dividing(by: 100)
Or, other ways to create 0.07 value but avoiding Double in the process include using strings:
let value = Decimal(string: "0.07") // or NSDecimalNumber(string: "0.07")
Or specifying the mantissa/significant and exponent:
let value = Decimal(sign: .plus, exponent: -2, significand: 7) // or NSDecimalNumber(mantissa: 7, exponent: -2, isNegative: false)
Bottom line, avoid Double representations entirely when using Decimal (or NSDecimalNumber), and you won't suffer the problem you described.
Declaring ranges in Ada is always done inclusively.
If i want a type that has all the integers from 0 to 42 (or as a mathmatical interval: [0, 42]) i declare it as follows:
type zero_to_42 is range 0 .. 42;
If i want to exclude the zero (the range (0, 42]), this is not an issue for discrete types:
type not_zero_to_42 is range (zero_to_42'First + 1) .. zero_to_42'Last;
but i still have to do this manually, there is no zero_to_answer'NextAfterFirst
For floating point types i have no idea how to do this properly. It's simple for excluding the zero, but excluding anything else seems implementation defined to me.
type works is digits 6 range 0.0 .. 42.0
type also_works is new works range (0.0 + works'small) .. 42.0
type broken is new works range 0.0 .. (42.0 - works'small)
since float values near 42.0 have less precision than floating point values near 0.0, 42.0 - works'small is rounded to 42.0
i could of course find a value by hand that works (e.g. 41.9999) but that seems ugly to me and might not work anymore when i change the number of digits that works has.
The 'Succ and 'Pred attributes can be used on floating-point values to return the next or previous machine numbers. If T is a floating-point type,
T'Succ(X)
is the smallest floating-point "machine number" > X, and
T'Pred(X)
is the largest floating-point machine number < X. Thus:
type Works is digits 6 range 0.0 .. 42.0;
subtype Exclusive is Works range 0.0 .. Works'Pred(42.0);
Or (since the range on the type declaration might not be relevant):
type Digits_6 is digits 6;
subtype Exclusive is Digits_6 range 0.0 .. Digits_6'Pred(42.0);
Or
type Exclusive is digits 6 range 0.0 .. Float'Pred(42.0);
assuming you know Float is a 32-bit IEEE float and Exclusive will also be one.
What is can be used here is 'Adjacent(near_value, towards_value)
type works is digits 6 range 0.0 .. 42.0
type also_works is new works range (0.0 + works'small) .. 42.0
type still_works is new works range 0.0 .. works'Adjacent(42.0, 0.0)
this looks for whichever value can be represented by the machine that is closest to near_value in the direction of towards_value
when printing out still_works'last and works'last very likely the result will look/be the same, but comparing the two won't work
declare
type works is digits 6 range 0.0 .. 42.0
subtype still_works is works range 0.0 .. works'Adjacent(42.0, 0.0)
begin
Text_IO.Put_Line(works'Image(works'Last));
Text_IO.Put_Line(still_works'Image(still_works'Last));
Text_IO.Put_Line(Boolean'Image(works'Last = still_works'Last));
end;
yields when compiled with gnat:
4.20000E+01
4.20000E+01
FALSE
You might be able to use the Ada 2012 dynamic predicate:
type Exclusive is new Float range 0.0 .. 42.0
with Dynamic_Predicate => Exclusive > 0.0 and then Exclusive < 42.0;
but GNAT seems to have troubles with this: GCC 4.8.1 is OK, GNAT GPL 2013 won’t even accept values of 1.0 or 41.0, and GCC 4.9.0-20140119 threw a bug box!
In a cocos2d game, I use arc4random to generate random numbers like this:
float x = (arc4random()%10 - 5)*delta;
(delta is the time between updates in the scheduled update method)
NSLog(#"x: %f", x);
I have been checking them like that.
Most of the numbers that I get are like this:
2012-12-29 15:37:18.206 Jumpy[1924:907] x: 0.033444
or
2012-12-29 15:37:18.247 Jumpy[1924:907] x: 0.033369
But for some reason I get numbers like this sometimes:
2012-12-29 15:37:18.244 Jumpy[1924:907] x: 71658664.000000
Edit: Delta is almost always:
2012-12-29 17:01:26.612 Jumpy[2059:907] delta: 0.016590
I thought it should return numbers in a range of -5 to 5 (multiplied by some small number). Why I am getting numbers like this?
arc4random returns a u_int32_t. The u_ part tells you that it's unsigned. So all of the operators inside the parentheses use unsigned arithmetic.
If you perform the subtraction 2 - 5 using unsigned 32-bit arithmetic, you get 232 + 2 - 5 = 232 - 3 = 4294967293 (a “huge number”).
Cast to a signed type before performing the subtraction. Also, prefer arc4random_uniform if your deployment target is iOS 4.3 or later:
float x = ((int)arc4random_uniform(10) - 5) * delta;
If you want the range to include -5 and 5, you need to use 11 instead of 10, because the range [-5,5] (inclusive) contains 11 elements:
float x = ((int)arc4random_uniform(11) - 5) * delta;
arc4random returns a u_int32_t, an unsigned type. The modulus is also performed using unsigned arithmetic, which yields a number between 0 and 9, as expected (by the way, don't ever do this; use arc4random_uniform instead). You then subtract 5, which is interpreted as an unsigned value, yielding a possibly huge positive value due to underflow.
The solution is to explicitly type the 5 by storing it in a variable of signed type or with a suffix (like 5L).
Looks like arc4random % 10 becomes less than 5, and you are working with negative integer later.
What is the value of delta?
Why is it that when I run this code in a loop, only whole numbers are printed in the console?
for (int i = 1; i <= 50; i++) {
zombieSpeed[i] = (((arc4random()%40)+2)/7);
NSLog(#"%f", zombieSpeed[i]);
}
The problem is here
zombieSpeed[i] = (((arc4random()%40)+2)/7);
instead of 40, 2, 7 you should use 40.0, 2.0, 7.0
Also make sure that ZombieSpeed is of float type
This line needs to use Float values (40.0, 2.0, 7.0)
zombieSpeed[i] = (((arc4random()%40)+2)/7);
The division is an integer division, use explicit decimal point as 40.0 or typecast, so that at least one operand is floating point, which upcasts the entire expression to be evaluated as floating point. Make sure that any left hand side variable to which you assign the computer value is of floating point type with equal or greater width (to preserve the precision).
I was facing with one minor issue, and I'm wondering: Why?
here we have some string:
[NSString stringWithFormat#"%.3f/%.3f/%.3f/%i", 1.0, 1.0, 1, 1];
in this case, result is 1.000/1.000/1/abra-kadabra like 34875689.
Why it's happens? Of course, I know, when we change the third value to 1.0, then everything will be okay.
So, please, explain me the deep proces of this operation.
Since you wrote %f, the compiler expects a float but recognizes an int. Writing 1 instead of 1.0 tells the compiler it's an integer constant instead of 1.0, which is a float constant.