Operators and Formatting in Zig
In this section, we'll explore two fundamental aspects of working with Zig: mathematical operators and format strings. Mathematical operators allow you to manipulate numeric data, while format strings enable precise control over how that data is presented in your output.
We'll first go over the common operators you will use to perform calculations, such as addition, subtraction, multiplication, and division. Then, we will dive into how Zig allows you to format the output of these calculations or any other data using different format specifiers. These formatters allow you to customize how integers, floating-point numbers, strings, and other data types appear when printed to the console.
By the end of this section, you should feel comfortable manipulating numbers in Zig and outputting them in a way that suits your needs. Let's get started with operators!
Operators in Zig
Operator | Description | Example |
---|---|---|
+ | Addition | var sum = a + b; |
- | Subtraction | var diff = a - b; |
* | Multiplication | var product = a * b; |
/ | Division | var quotient = a / b; |
% | Modulus (Remainder) | var remainder = a % b; |
Formatters in Zig
Formatter | Description | Example |
---|---|---|
{d} | Integer (decimal) | std.debug.print("{d}", .{123}); |
{x} | Integer (hexadecimal) | std.debug.print("{x}", .{0x1a3f}); |
{b} | Integer (binary) | std.debug.print("{b}", .{155}); |
{} | General placeholder (for various types) | std.debug.print("{}", .{true}); |
{c} | Character | std.debug.print("{c}", .{'A'}); |
{s} | String | std.debug.print("{s}", .{"Hello, Zig"}); |
Manipulating Data Using Mathemetatical Operators
touch maths.zig
Let's look at some mathematical operators to start:
const std = @import("std");
pub fn main() void {
const num1 = 100;
const num2: f32 = 200.0;
var sum: i32 = num1 + num2; // note these are vars because they mutate
var product: i32 = num1 * num2;
var difference: i32 = num1 - num2;
var quotient: f32 = num1 / num2;
std.debug.print("sum {d}, product: {d}, difference: {d}, quotient: {d}\n", .{ sum, product, difference, quotient });
sum += 10; // sum = sum + 10;
product *= 2; // product = product * 2;
difference -= 5; // difference = difference - 5;
quotient /= 3; // quotient = quotient / 3
std.debug.print("sum {d}, product: {d}, difference: {d}, quotient: {d}\n", .{ sum, product, difference, quotient });
}
> zig run maths.zig
sum 300, product: 20000, difference: -100, quotient: 0.5
sum 310, product: 40000, difference: -105, quotient: 0.16666667
Modulus function
touch modulus.zig
In many languages a way to figure out if a number is odd or even is modulus, which determines a remainder between 2 numbers. Zig allows you to represent this 2 ways: 1. const remainder = 15%2;
, 2 is using a function - let's take a look at @mod()
function.
const std = @import("std");
pub fn main() void {
const remainder = @mod(15, 2); // 15/2 = 7 with a remainder of 1
std.debug.print("Remainder is {}\n", .{remainder});
}
> zig run modulus.zig
Remainder is 1
Standard Output and Format Strings
Standard output vs Standard Error
touch stdout.zig
const std = @import("std");
pub fn main() !void { // You need the ! because the standard output writer we will create is capable of throwing an error
//exclamation void usage is called an error union
const message = "Howdy, Zig programmers!";
var stdout = std.io.getStdOut().writer(); // writer function
try stdout.print("Message : {s}\n", .{message}); // try means it could throw an error
}
> zig run stdout.zig
Message : Howdy, Zig programmers!
This try method using stdout as a writer function is prefered over the std.debug.print method we have gotten used to because it will throw an error on the main function.
Format Strings
Format strings allow us to interpolate and format data within our strings
touch format.zig
const std = @import("std");
pub fn main() void {
const negativeNumber = -123;
const hexNumber = 0x1a3f;
const binaryNumber = 155;
const truthValue = true;
const piValue = 3.14159;
const alphabetChar = 'A'; // note single quote
const greetingMessage = "Hello, Zig";
std.debug.print("Integer (decimal): {d}\n", .{negativeNumber});
std.debug.print("Integer (hexadecimal): {x}\n", .{hexNumber});
std.debug.print("Integer (binary): {b}\n", .{binaryNumber});
std.debug.print("Boolean : {}\n", .{truthValue});
std.debug.print("Float : {d}\n", .{piValue});
std.debug.print("Character : {c}\n", .{alphabetChar});
std.debug.print("String: {s}\n", .{greetingMessage});
}
> zig run format.zig
Integer (decimal): -123
Integer (hexadecimal): 1a3f
Integer (binary): 10011011
Boolean : true
Float : 3.14159
Character : A
String: Hello, Zig
Currecy Converter Project!
Using what you've learned, create a currency converter that will convert the following:
- USD -> Euro = 0.93
- USD -> GBP = 0.82
- USD to JPY = 134.25
Calculate the equivalent amounts for $100USD in each
- Output the results with 2 decimal places
- "_._ USD is equivalent to EUR .__" for example.
- Use a writer instead of debug for your print statements
Take the challenge, then come back here for the answer.
const std = @import("std");
pub fn main() !void {
var stdout = std.io.getStdOut().writer();
const message = "100.00 message is equivalent to ";
const converting = .{ "Euro", "GBP", "JPY" };
const usd: f32 = 100.0; // amount to convert
const euro: f32 = usd * 0.93;
const gbp: f32 = usd * 0.82;
const jpy: f32 = usd * 134.25;
try stdout.print("{s} {d:.2} {s}\n", .{ message, euro, converting[0] });
try stdout.print("{s} {d:.2} {s}\n", .{ message, gbp, converting[1] });
try stdout.print("{s} {d:.2} {s}\n", .{ message, jpy, converting[2] });
}
> zig run currency.zig
100.00 USD is equivalent to 93.00 Euro
100.00 USD is equivalent to 82.00 GBP
100.00 USD is equivalent to 13425.00 JPY
Conclusion
In this section, you’ve learned how to perform basic mathematical operations in Zig and format output using format strings. Understanding operators is crucial for manipulating data, while formatters give you the power to control how that data is presented. Whether you're working with integers, floats, or strings, these concepts are fundamental for building more complex applications.
By mastering these tools, you'll be able to write more efficient and readable code. As you move forward, remember that these foundational skills are applicable in many scenarios, from simple calculations to more advanced tasks like file handling or data parsing. Keep practicing, and you'll soon be able to tackle more complex challenges in Zig with confidence!
Drew is a seasoned DevOps Engineer with a rich background that spans multiple industries and technologies. With foundational training as a Nuclear Engineer in the US Navy, Drew brings a meticulous approach to operational efficiency and reliability. His expertise lies in cloud migration strategies, CI/CD automation, and Kubernetes orchestration. Known for a keen focus on facts and correctness, Drew is proficient in a range of programming languages including Bash and JavaScript. His diverse experiences, from serving in the military to working in the corporate world, have equipped him with a comprehensive worldview and a knack for creative problem-solving. Drew advocates for streamlined, fact-based approaches in both code and business, making him a reliable authority in the tech industry.