Literal numbers in FloatingPoint protocol
The FloatingPoint
protocol inherits from ExpressibleByIntegerLiteral
via the inheritance chain
FloatingPoint - SignedNumeric - Numeric - ExpressibleByIntegerLiteral
and that is why the second function uprightAngle2
compiles: Values
of the type T
are created from the integer literals 2
and 3
.
The first function uprightAngle1
does not compile because
the FloatingPoint
protocol does not inherit from ExpressibleByFloatLiteral
, i.e. values of type T
can not
be created from a floating point literal like 1.5
.
Possible solutions:
Create rational values as
let half: T = 1/2
. (Notlet half = T(1/2)
,
that would truncate the division result before creating theT
value.)Replace
FloatingPoint
byBinaryFloatingPoint
(which inherits
fromExpressibleByFloatLiteral
).
For more information about the design of the floating point
protocols see SE-0067 Enhanced Floating Point Protocols.
The floating point types in the Swift Standard Library (Double
, Float
, CGFloat
, Float80
) as well asCGFloat
from the Core Graphics framework all conform to theBinaryFloatingPoint
protocol, so this protocol is "sufficiently
generic" for many applications.
How to use FloatingPoint generic type for Float/Double
One problem is that FloatingPoint
is not a subprotocol of ExpressibleByFloatLiteral
, so your floating-point literals cannot necessarily be converted to T
. You can solve this either by changing FloatingPoint
to BinaryFloatingPoint
(which is a subprotocol of ExpressibleByFloatLiteral
) or by adding ExpressibleByFloatLiteral
as a separate requirement.
Then you will run into the problem that there is no pow
function that is generic over FloatingPoint
, and no member of FloatingPoint
or BinaryFloatingPoint
that performs exponentiation. You can solve this by creating a new protocol and conforming the existing floating-point types to it:
protocol Exponentiatable {
func toPower(_ power: Self) -> Self
}
extension Float: Exponentiatable {
func toPower(_ power: Float) -> Float { return pow(self, power) }
}
extension Double: Exponentiatable {
func toPower(_ power: Double) -> Double { return pow(self, power) }
}
extension CGFloat: Exponentiatable {
func toPower(_ power: CGFloat) -> CGFloat { return pow(self, power) }
}
Note that there is also a Float80
type, but the standard library doesn't provide a pow
function for it.
Now we can write a working generic function:
func srgb2linear<T: FloatingPoint>(_ S: T) -> T
where T: ExpressibleByFloatLiteral, T: Exponentiatable
{
if S <= 0.04045 {
return S / 12.92
} else {
return ((S + 0.055) / 1.055).toPower(2.4)
}
}
Coding conventions for number literal suffix?
From the Java Tutorials:
Floating-Point Literals
A floating-point literal is of type float if it ends with the letter F or f; otherwise its type is double and it can optionally end with the letter D or d.
The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).
double d1 = 123.4;
// same value as d1, but in scientific notation
double d2 = 1.234e2;
float f1 = 123.4f;
This tells you that:
- Both D and d have the same meaning - just as you observed
- "By convention [D or d are] omitted" because they are the default
Questions of the type "what is better" are offtopic on StackOverflow since they can't have a correct or incorrect answer, only opinions.
But if you ask for a convention I would tend to follow what I've found above - omit the suffix.
Literals in Swift generics
You can create a type constraint (MyFloats
below) to which your floating point types conform. You let this type constraint itself conform to Comparable
, so that you may make use of the less than binary infix operator <
when comparing the values of your generics. Also, for your example given above, the MyFloats
type constraint need contain only a single blueprint; an initializer for a Double
argument. This initalizer already exists for Double
, Float
and CGFloat
types, but since a protocol cannot know which types that conforms to it, you need to include this blueprint.
protocol MyFloats : Comparable {
init(_ value: Double)
}
extension Double : MyFloats { }
extension Float : MyFloats { }
extension CGFloat : MyFloats { }
func sign<T: MyFloats> (value:T) -> T {
if value < T(0.0) {
return T(-1.0)
}
if value > T(0.0) {
return T(1.0)
}
return T(0.0)
}
Is there any C++ style guide that talks about numeric literal suffixes?
There is no general style guide that I've found. I use capital letters and I'm picky about using F for float literals and L for long double. I also use the appropriate suffixes for integral literals.
I assume you know what these suffixes mean: 3.14F
is a float
literal, 12.345 is a double literal, 6.6666L is a long double literal.
For integers: U
is unsigned
, L
is long
, LL
is long long
. Order between U
and the L
s doesn't matter but I always put UL
because I declare such variables unsigned long
for example.
If you assign a variable of one type a literal of another type, or supply a numeric literal of one type for function argument of another type a cast must happen. Using the proper suffix avoids this and is useful along the same lines as static_cast is useful for calling out casts. Consistent usage of numeric literal suffixes is good style and avoids numeric surprises.
People differ on whether lower or upper case is best. Pick a style that looks good to you and be consistent.
Why can a numeric literal be interpreted as an NSNumber in Swift?
NSNumber
conforms to the ExpressibleByBooleanLiteral
, ExpressibleByFloatLiteral
and ExpressibleByIntegerLiteral
protocols, which means that it can be
initialized from a boolean, floating point, or integer literal:
let n1: NSNumber = false
let n2: NSNumber = 12.34
let n3: NSNumber = 123
Related Topics
Why Do I Get Rgb Values of (0,0,0) for an Nsimage with a Transparent Background
Reduce Float Precision Using Regexp in Swift
Appdelegate#Applicationdidfinishlaunching Not Called for Swift 4 Macos App Built from Command Line
Cannot Authenticate User for Aws Appsync with Swift Sdk
On Demand Resources "0 Asset Packs"
Testing a Class Which Preserves Its State in Private Variables
Access Each Header and Controls in The Tableview in Swift
How to Synchronize Access to a Property That Has Didset
Do Not Copy Swift Libraries with Xcode 8
Setadvertisertrackingenabled Is Not Found in Settings Class of Fbsdk
Nskeyedunarchiver Decodeobjectforkey: Cannot Decode Object of Class for Key (Ns.Objects)
Swift Flatmap on Array with Elements Are Optional Has Different Behavior
Does Realm Support Computed Property in Swift
Swift Textview Align with English and Arabic Languages
Assigning Values to Tuple in for Loop
How to Enable a Button in Different Cases in Swift