๐ผ๏ธBinaryBitPatternView
Last updated
Last updated
โฌ๏ธ ้่ฆ๏ผ .binary(digits:)
// 2022.02.12 / (no wrap) apply .fixedSize() to all `Text`s
// + (refactor) .bitsView()
// / (refactor) .nowrapText() + `modify` closure
import SwiftUI
// T: BinaryFloatingPoint & CustomStringConvertible
struct BinaryBitPatternView<T: BinaryFloatingPoint>: View where T: CustomStringConvertible {
// (binary) floating-point number
let x: T // variable
var optionalName: String? = nil // optional variable name
// view body
var body: some View {
let t = type(of: x)
let sign = x.sign == .plus ? "+" : "-"
let signBit = x.sign == .plus ? "0" : "1"
// ๐BinaryInteger + .binary(digits:)
// integer -> array of bits ([string])
let exp = x.exponentBitPattern.binary(digits: t.exponentBitCount)
let significand = x.significandBitPattern.binary(digits: t.significandBitCount)
// container view
VStack(spacing: 8) {
// title
HStack(alignment: .firstTextBaseline, spacing: 24) {
let bits = 1 + t.exponentBitCount + t.significandBitCount
nowrapText("\(t)") { $0.font(.largeTitle).bold() }
nowrapText("floating-point representation", .secondary)
nowrapText("(\(bits)-bit)")
}
// floating-point representation
HStack(alignment: .top, spacing: 1) {
// sign bit
bitsView([signBit], "\(sign)", .pink)
// exponent bits
bitsView(exp, "exponent (\(t.exponentBitCount)-bit)", .blue)
// significand bits
bitsView(significand, "significand (\(t.significandBitCount)-bit)", .green)
}
// calculation
HStack() {
// variable name (optional view)
// name =
optionalName.map { name in
HStack {
nowrapText(name, .blue) { $0.bold() }
nowrapText("=", .secondary)
}
}
// x =
nowrapText(x, .orange)
nowrapText("=", .secondary)
// (sign) (significand) ร (radix)^(exponent)
nowrapText(sign, .purple)
nowrapText(x.significand)
nowrapText("ร", .purple)
nowrapText(t.radix)
nowrapText(x.exponent)
.scaleEffect(0.6, anchor: .leading)
.offset(x: -8, y: -10)
}
.padding()
.border(.pink)
.padding(.top)
}
}
}
extension BinaryBitPatternView {
/// a little square view for each bit
func bit(_ b: String, bg: Color = .green, size: CGFloat = 25) -> some View {
Text("\(b)").font(.system(.caption, design: .monospaced))
.foregroundColor(.black)
.frame(width: size, height: size)
.background(bg)
.border(.primary, width: 1)
}
/// bits view
func bitsView(_ bits: [String], _ subtitle: String, _ color: Color) -> some View {
VStack {
HStack(spacing: 1) {
ForEach(0..<bits.count) { bit(bits[$0], bg: color) }
}
Text(subtitle).fixedSize() // no wrap
}
}
/// no-wrap text
func nowrapText<T: CustomStringConvertible>(
_ x: T,
_ color: Color = .primary,
modify : (Text) -> Text = { $0 } // text modifier
) -> some View {
modify(Text("\(String(describing: x))"))
.fixedSize().foregroundColor(color)
}
/// convenience init
init(_ x: T, name: String? = nil) { self.init(x: x, optionalName: name) }
}
import SwiftUI
struct ContentView: View {
var body: some View {
ScrollView(.horizontal) {
VStack(spacing: 50) {
BinaryBitPatternView(Float.pi, name: "pi")
BinaryBitPatternView(Float.pi.ulp, name: "pi.ulp")
BinaryBitPatternView(Double.greatestFiniteMagnitude, name: ".greatestFiniteMagnitude")
}
.scaleEffect(0.7)
}
}
}
Swift โฉ String โฉ String(_:radix:uppercase:) โญ๏ธ ๅฐๆดๆธ็จไบ้ฒไฝใๅ ซ้ฒไฝใๅๅ ญ้ฒไฝ่กจ็คบใ
custom View for BinaryFloatingPoint numbers.
uses a lot of Texts.
ๅ๏ผๆนๅ็บใFloatingPointViewใโ
2022.02.12
โฌ๏ธ ้่ฆ๏ผ .binary(digits:)
import SwiftUI
struct BinaryBitPatternView<T: BinaryFloatingPoint>: View {
let x: T
var body: some View {
// type of x
let t = type(of: x)
let sign = x.sign == .plus ? "+" : "-"
// x -> bits -> string -> array of bits (string)
let exp = x.exponentBitPattern.binary(digits: t.exponentBitCount)
let significand = x.significandBitPattern.binary(digits: t.significandBitCount)
VStack(spacing: 8) {
// title
Text("\(String(describing: t))")
.font(.largeTitle).bold()
+ Text(" floating-point representation (\(1 + t.exponentBitCount + t.significandBitCount)-bit)")
// floating-point representation
HStack(alignment: .top, spacing: 1) {
// sign bit
VStack {
bit(String(x.signBitPattern.first!), bg: .pink)
Text("\(sign)")
}
// exponent bits
VStack {
HStack(spacing: 1) {
ForEach(0..<exp.count) {
bit(exp[$0], bg: .blue)
}
}
Text("exponent (\(t.exponentBitCount)-bit)")
}
// significand bits
VStack {
HStack(spacing: 1) {
ForEach(0..<significand.count) {
bit(significand[$0])
}
}
Text("significand (\(t.significandBitCount)-bit)")
}
}// HStack
// calculation
HStack(spacing: 0) {
Text("\(String(describing: x)) = \(sign)\(String(describing: x.significand)) ร \(t.radix)").fixedSize()
Text("\(String(describing: x.exponent))")
.fixedSize()
.scaleEffect(0.6, anchor: .leading)
.offset(y: -10)
}
.padding()
.border(.pink)
.padding(.top)
}
}
}
extension BinaryBitPatternView {
/// a little square for each bit
func bit(_ b: String, bg: Color = .green, size: CGFloat = 25) -> some View {
Text("\(b)").font(.system(.caption, design: .monospaced))
.foregroundColor(.black)
.frame(width: size, height: size)
.background(bg)
.border(.primary, width: 1)
}
/// convenience init
init(_ x: T) { self.init(x: x) }
}