Print Double as Int - if not a Double value - xcode

I want my Double to display as an Int, if the value is an integer - otherwise as a Double.
Example;
var Value = Double()
.
Value = 25.0 / 10.0
Now I want Value to display 2.5 (when inserted to label)
.
Value = 20.0 / 10.0
Now I want Value to display 2 - and NOT 2.0

One approach is to obtain the fractional part using % operator, and check if it is zero:
let stringVal = (Value % 1 == 0)
? String(format: "%.0f", Value)
: String(Value)

One classic way is to establish a value for epsilon which represents your tolerance for considering a value close enough to an Int:
// How close is close enough to be considered an Int?
let kEPSILON = 0.0001
var val = 1.9999
var str: String
if abs(val - round(val)) < kEPSILON {
str = String(Int(round(val)))
} else {
str = String(val)
}
print(str) // "2"

I like dasblinkenlight's and vacawama's answers, but also want to contribute another one: Using NSNumberFormatter
let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
formatter.alwaysShowsDecimalSeparator = false
let string0 = formatter.stringFromNumber(25.0/10.0)!
let string1 = formatter.stringFromNumber(20.0/10.0)!
print(string0)
print(string1)
result:
2.5
2
The most important advantage: It is localized. On german devices it will show 2,5 instead of 2.5, just as it would be expected by a german speaking user.

To display numbers as text, use NSNumberFormatter(). You can set its minimumFractionDigits
property to zero:
let fmt = NSNumberFormatter()
fmt.minimumIntegerDigits = 1
fmt.maximumFractionDigits = 4
fmt.minimumFractionDigits = 0
print(fmt.stringFromNumber(25.0 / 10.0)!) // 2,5
print(fmt.stringFromNumber(20.0 / 10.0)!) // 2
print(fmt.stringFromNumber(2.0 / 7.0)!) // 0,2857
If you want a decimal period, independent of the user's locale,
then add
fmt.locale = NSLocale(localeIdentifier: "en_US_POSIX")
Swift 3:
let fmt = NumberFormatter()
// Optional:
fmt.locale = Locale(identifier: "en_US_POSIX")
fmt.minimumIntegerDigits = 1
fmt.maximumFractionDigits = 4
fmt.minimumFractionDigits = 0
print(fmt.string(from: 25.0 / 10.0 as NSNumber)!) // 2,5
print(fmt.string(from: 20.0 / 10.0 as NSNumber)!) // 2
print(fmt.string(from: 2.0 / 7.0 as NSNumber)!) // 0,2857

Working on a calculator on Swift 4, I treated the number variables as String so I could display them on screen and converted them to Double for the calculations, then convert them back to String to display the result. When the result was an Int I didn't want the .0 to be displayed as well so I worked this out and it was pretty simple
if result.truncatingRemainder(dividingBy: 1) == 0{
screenLabel.text = String(Int(result))
}
else{
screenLabel.text = String(result)
}
so result is the variable in Double format, if divided by 1 it gives us 0 (perfect division means its an Int), I convert it in Int.

Related

F# - Is this a good way to validate and keep a value between two bounds?

I have various values which I would like to keep between certain bounds: e.g. Width of Column from 10 to 50 inclusive; or Number Of Rows from 1 to 100 inclusive. The values are coming from a process external to my F# code.
When a given value falls below the lower bound I would like the value to be given the minimum bound value.
When the given value shoots above the upper bound I would like the value to be given the maximum bound value.
Otherwise I would accept the given value.
For example:
Bounds = 10 to 50 – Given Value = 3 – Result Value = 10
Bounds = 10 to 50 – Given Value = 200 – Result Value = 50
Bounds = 10 to 50 – Given Value = 32 – Result Value = 32
I have come up with some code but I’m not sure if it is taking things too far or whether I am doing it a silly way.
It look like it’s easy to reason how it’s working but I’m not sure about it, for no reason that I can put my finger on.
type ValueAndBounds = { Value : int; Lower : int; Upper: int }
let (|TooSmall|TooLarge|CorrectSize|) input =
if input.Value < input.Lower then TooSmall
elif input.Value > input.Upper then TooLarge
else CorrectSize
let keepWithinBounds input =
match input with
| TooSmall -> input.Lower
| TooLarge -> input.Upper
| CorrectSize -> input.Value
type ColumnWidth = ColumnWidth of int
let width = ColumnWidth (keepWithinBounds { Value = 32; Lower = 10; Upper = 50 })
Is there some way I can improve this?
Have I gone too far for this sort of simple thing (is it more than necessary)?
Is there a better way to do this differently?
personally I'd just define a simple function, and use a bit of partial application,
let keepWithBounds min max value =
if (value < min) then
min
elif (value > max) then
max
else
value
then your code can do something like
let handleWidth = keepWithBounds 10 50
let width1 = handleWidth 32
let width2 = handleWidth 60
Here’s my own answer which uses both active patterns, and partial application, and allows for generic use without the need for an extra type.
let (|TooSmall|TooLarge|CorrectSize|) (lower, upper, input) =
if input < lower then TooSmall
elif input > upper then TooLarge
else CorrectSize
let keepWithinBounds lowerBound upperBound input =
match (lowerBound, upperBound, input) with
| TooSmall -> lowerBound
| TooLarge -> upperBound
| CorrectSize -> input
type ColumnWidth = ColumnWidth of int
type RowHeight = RowHeight of int
type Temperature = Temperature of float
let createColumnWidth = keepWithinBounds 10 40
let createRowHeight = keepWithinBounds 60 100
let createTemperature = keepWithinBounds 0.0 20.0
let width = ColumnWidth (createColumnWidth 50)
let height = RowHeight (createRowHeight 50)
let temp = Temperature (createTemperature 33.1)
//val width : ColumnWidth = ColumnWidth 40
//val height : RowHeight = RowHeight 60
//val temp : Temperature = Temperature 20.0

Set value for Progress bar in xamarin

I have value of a field coming from server lfrom 1 to 100 which is to show progress of that field. But I checked that we can provide value to progress bar from 0 to1. How can i convert this. I did something like this but didn't work
Int Field = 12;
Decimal d = Field / 100;
Decimal dc = Math.Round(d,1); //to round to one decimal place
return dc;
This is returning 0.
I tried this too:
double d = (double)(Progress / 100);
double dc = Math.Round(d, 1);
return dc;
This is also returning 0.
if you want maximum precision, you can convert an old range of values in a new range maintaining the ratio with this formula:
var OldRange = (OldMax - OldMin);
var NewRange = (NewMax - NewMin);
//i'm using round here has you requested, but its better to dont use it to achieve best results
var NewValue = Math.Round(((OldValue - OldMin) * NewRange) / OldRange) + NewMin, 1);
In your case, taking for example the number 12, this will be:
var OldRange = 99 //(100 - 1);
var NewRange = 1 //(1 - 0);
var NewValue = Math.Round(((12 - 1) * NewRange) / OldRange) + 0, 1);
Concluding the number 12 in the old range is 0.1 in the new range.
Or if you dont care that the old range starts from 1 and the new from 0, you can just divide by 100 and round the value:
Int field = 12;
Decimal d = field / 100;
Decimal dc = Math.Round(d,1); //to round to one decimal place
return dc;
Please note that in c# the divide operator is / and not % (wich is the modulus)
Turns out "/" operator doesn't work in C#
NO, "/" operator do work in C#.
You get a zero because Field / 100; is int/int, the result is 0;
Progress / 100 is the same, int/int get 0;
To make your code work. You can define the field as type Decimal :
Decimal Field = 12;
Decimal d = Field / 100;
Decimal dc = Math.Round(d, 1);
Or cast the 100 to Decimal:
int Field = 12;
Decimal d = Field /(Decimal)100;
Decimal dc = Math.Round(d, 1);
You can see detailed answer in these two threads: why-does-integer-division-in-c-sharp-return-an-integer-and-not-a-float
and
how-can-i-divide-two-integers-to-get-a-double

Better Random Number Ranges In Swift 3

Before I upgraded to Swift 3 (Xcode 8) my random position start looked like this:
func randomStartPosition(range: Range<Int> = 45...(Int(self.frame.size.height)-45)) -> Int {
let min = range.startIndex
let max = range.endIndex
return Int(arc4random_uniform(UInt32(max - min))) + min }
Which stopped working after the conversion because it was updated to this:
func randomSmallObjectsStartPosition(_ range: Range<Int> = 25...(Int(self.frame.size.height)-25)) -> Int {
let min = range.lowerBound
let max = range.upperBound
return Int(arc4random_uniform(UInt32(max - min))) + min }
Which was worked out because I ended up learning about GamePlayKit:
Start by:
import GameplayKit
Then you can easily make new random variables using GamePlayKit:
You can read up on the apple site but basically this gives you more "hits" in the middle:
lazy var randomStartPosition = GKGaussianDistribution(randomSource: GKARC4RandomSource(), lowestValue: 0, highestValue:100)
And this will cycle through the random values until they are all consumed, then start again.
lazy var randomShuffle = GKShuffledDistribution(randomSource: GKARC4RandomSource(), lowestValue: 0, highestValue:100)
And lastly the totally random value generator:
lazy var totallyRandom = GKRandomDistribution(lowestValue: 1, highestValue: 100)
An example of how to use:
MyObject.position = CGPoint(x: self.frame.size.width + 20, y: CGFloat(totallyRandom.nextInt()) )
This will put my object off the screen on the far right and put it at a completely random position on the Y axis.

Swift 2 - add decimal 0 to CGFloat

I am trying to convert a string into CGFloat number.
The code I have cuts out the last digit if equal to 0.
How can I prevent to cut out the zeros?
let str = "17.30"
let flt = CGFloat((str as NSString).doubleValue) + 2.0
print(flt) // 19.3 -- should be 19.30
CGFloat can't do that, convert the float back to String
print(String(format: "%.2f", flt)) // 19.30
For swift 4
Try using NumberFormatter in .decimal format:
let text = "123456.789"
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
formatter.maximumFractionDigits = 2
let value = formatter.string(from: text! as NSNumber)!
print(value)
Output: 123,456.78
The CGFloat is just a number (so 17.3 and 17.30 is the same value for it); what you're really concerned is how to set the String representation of your CGFloat number.
As an alternative to #vadian:s solution, you can make use of an NSNumberFormatter as follows
/* Your CGFloat example */
let str = "17.30"
let flt = CGFloat((str as NSString).doubleValue) + 2.0
/* Use NSNumberFormatter to display your CGFloat
with exactly 2 fraction digits. */
let formatter = NSNumberFormatter()
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 2
print(formatter.stringFromNumber(flt)!)
/* 19.30 */

Swift: convert a 2's complement number in String form into an Double

I have a sensor which is generating 16 bit values in 2's complement in a string form. I need to do some maths with these value so ultimately I need to convert the to Doubles. Where "f112" is 2's complement example value which will generates -3822.
I am very much a Swift beginner and feel there must be an easier way?
let value2 = UInt32("f112",radix:16)
if value2 > 32767 {
// handle -ve values
value5 = Int32(bitPattern:value2! | 0xFFFF0000)
} else {
// +ve
value5 = Int32(bitPattern:value2! )
}
let doubleValue = Double(value5)
There are probably several solutions, this is one.
First it creates the UInt16 value and converts it to Int to be able to do 32 bit math.
Then it subtracts 0x10000 (65536) if the most significant bit is set.
let value2 = Int(UInt16("f112",radix:16)!)
let doubleValue = value2 > 0x7fff ? Double(value2 - 0x10000) : Double(value2)
or using the bitwise NOT operator (~)
let value2 = UInt16("f112",radix:16)!
let doubleValue = value2 > 0x7fff ? -Double(~value2 + 1) : Double(value2)
my solution is a little bit different from vadian's
let str = "f112"
// if you are sure about str (so force unwrapping is fine)
let d = Double(Int16(bitPattern: UInt16(str, radix: 16)!)) // -3822
// or more 'safe' version, which return 0 in case of invalid parameter
let d0 = Double(Int16(bitPattern: UInt16(str, radix: 16) ?? 0)) // -3822
by the way
Int16("f112", radix: 16) == nil // true!
looks like a bug for me ...

Resources