Author: Amber Colvin

  • Computer File: From Stored Bytes to an Open Document

    Computer File: From Stored Bytes to an Open Document

    A computer file is a named collection of digital data that an operating system can store, identify, and retrieve. The data may be a document’s text, a photograph’s pixels, program instructions, or configuration settings. A file is not the same as its displayed name: the content is encoded in bytes, while the name helps people and software find and interpret it.

    To understand what is a computer file in practice, follow a saved document from storage to the application that opens it. The operating system connects its bytes with a filename, location, metadata, and an app association.

    What Is a Computer File?

    A file begins as bytes recorded on storage, such as an SSD, hard drive, memory card, or network volume. The filesystem organizes those bytes and keeps a record that identifies where they belong. When you save a document named Report.docx, the document’s text, formatting, images, and other content become data in that file.

    The file’s identity includes more than its visible name. The filesystem also tracks its location and may assign an internal identifier. If you move the document to another folder, the bytes may remain unchanged while the path changes. If you edit and save it, the content and often the file size or modification time change.

    Computer File Definition: How Names, Extensions, and Formats Differ

    A useful computer file definition separates four related terms:

    • Content: The actual bytes stored in the file. They represent text, images, audio, code, or another kind of data.
    • Filename: The human-readable label, such as Report.docx. It can usually be changed without changing the content.
    • Extension: The ending after the final period, such as .docx, .jpg, or .pdf. It gives the operating system and applications a useful clue about the file type.
    • Format: The internal rules that explain how the bytes are organized and decoded. DOCX, JPEG, and PDF each use different structures.

    An extension is not proof that the internal format matches it. Renaming photo.jpg to photo.pdf changes the label, not the bytes, so it does not convert a JPEG into a PDF. The renamed file may fail to open or may be sent to an unsuitable application. Conversion requires software to read the original format and write new content in the target format.

    How Do Folders and File Paths Locate a File?

    Folders, also called directories, group files and other folders into a hierarchy. A document might be inside the Documents folder, which is inside a user account folder. This structure lets different files have the same name when they occupy different locations.

    A file path describes that location. An absolute path starts at the storage system’s root or drive, such as C:\Users\Ana\Documents\Report.docx on Windows or /home/ana/Documents/Report.docx on a Unix-based system. It identifies the file independently of the current folder.

    A relative path starts from a defined current folder. If an application is working in /home/ana/Documents, the relative path Report.docx points to the document there. A path such as Archive/Report.docx points to a file in an Archive subfolder. The operating system resolves the path through each directory until it reaches the file record.

    How Do Size, Timestamps, Permissions, and App Associations Matter?

    Files carry metadata: information about the file rather than part of its main content. Common metadata includes:

    • Size: The amount of storage used, usually shown in bytes, kilobytes, megabytes, or gigabytes.
    • Timestamps: Dates such as when the file was created, modified, or last accessed. The exact fields and behavior vary by filesystem.
    • Permissions: Rules controlling who may read, change, run, or delete the file.
    • Ownership and location: The account associated with the file and the directory containing it.

    When you double-click a file, the operating system uses its extension, file type information, or other clues to select an associated application. A DOCX file may open in a word processor, while a JPEG may open in an image viewer. The application then reads the stored bytes according to the format’s rules. If the name, extension, or internal content conflicts, opening may produce an error or the wrong app.

  • App vs Widget: What Is the Difference?

    App vs Widget: What Is the Difference?

    In an app vs widget comparison, an app is the complete interactive product, while a widget is a focused interface for viewing information or performing a limited action. Use the app for sustained workflows and the widget for glanceable updates, simple controls, or fast access.

    The key difference is not simply size. An app can provide a full interface and operate as the main destination for a task. A widget usually appears inside another environment, such as a phone home screen, desktop, dashboard, or website, and exposes selected data or actions from a larger service.

    App vs Widget: What an App Is and How It Works

    An app is software built to handle a broad set of tasks within its own interface. It may be installed on a phone or computer, opened from an icon or link, and used independently of any particular screen layout. Although many apps rely on cloud services, they remain the primary place where users manage the experience.

    Apps support deeper interaction. A weather app, for example, can show hourly and extended forecasts, radar maps, saved locations, severe-weather alerts, notification settings, and account preferences. A calendar app can create events, invite attendees, search past appointments, and manage multiple calendars.

    Apps also control their own navigation and lifecycle more fully. They can open to a home screen, move between detailed views, save user settings, and guide a multi-step workflow. Content may refresh when the app opens or in the background, subject to the operating system, permissions, and network access.

    What is the difference between a widget and an app? Placement and Host Dependence

    A widget is a focused interface placed inside a host environment. The host may be a phone operating system, a desktop, a dashboard, a lock screen, or a website. The widget can display data, offer controls, or link to a deeper experience without reproducing the full app.

    The difference between widget and app is therefore largely about independence and scope. An app can usually be launched as the main destination for a task. A widget is normally dependent on its host and, often, on a companion app or service that supplies its data and actions. An embedded widget may instead depend on the website or dashboard platform where it is placed.

    A widget does not have to be a small square. A home-screen weather card, an analytics chart on a business dashboard, and an embedded booking panel on a website are all widgets, even though they have different sizes and layouts. Their shared characteristic is that they provide a bounded function within a larger environment.

    Widgets often use cached or scheduled updates rather than refreshing continuously. The host platform may limit refresh frequency to protect battery life and performance. A widget can therefore show recent data while the full app retrieves more current information when opened. App updates and widget updates may also be delivered together when the companion software changes.

    The difference between an app and a widget in One Everyday Task

    Consider checking the weather before leaving home. A weather widget can show the current temperature, precipitation risk, and a short forecast on a phone home screen or dashboard. It may include a refresh control or open the full weather app when tapped. This is useful when the goal is a quick decision.

    The weather app supports a longer interaction. It can provide hourly forecasts, radar, air-quality readings, multiple locations, alerts, historical data, and detailed settings. Planning a trip or investigating changing conditions requires the app because those tasks need navigation, comparison, and richer controls.

    The same pattern applies across services:

    • A calendar widget exposes upcoming appointments, while the calendar app creates and edits events.
    • A music widget shows playback controls, while the music app searches, organizes, and queues content.
    • A package-tracking widget shows delivery status, while the app manages several shipments and notification preferences.
    • A finance dashboard widget displays selected metrics, while the full app supports analysis, reporting, and account management.

    These widgets expose app or service data without duplicating the whole app. They reduce the number of steps for a narrow task while preserving the full interface for users who need more control.

    When Should You Use an App or a Widget?

    Choose an app when the task involves sustained attention, several steps, detailed information, creation or editing, or repeated navigation. Apps are the better fit for writing, editing photos, managing projects, booking complex travel, comparing options, and configuring preferences.

    Choose a widget when users mainly need to glance at changing information or complete a quick action. Widgets work well for weather, calendar reminders, timers, music controls, deliveries, battery status, and dashboard metrics. They can also serve as shortcuts into a specific app screen.

    For product and interface planning, pair both when the task has two levels of intent: use a widget for immediate awareness and a clear handoff to the app for deeper work. The app supplies the complete workflow; the widget supplies timely access where the user already is.

  • C Boolean Type: _Bool, bool, true, and false

    C Boolean Type: _Bool, bool, true, and false

    The C boolean type is based on the built-in _Bool type. A Boolean object stores either 0 or 1, although C conditions can evaluate any integer or pointer value as false or true. The value 0 and a null pointer are false; nonzero integers and non-null pointers are true.

    For C99 through C17 code, stdbool.h supplies the familiar bool, true, and false names. Use either the built-in type or the header-provided names consistently within a project.

    The C boolean type: _Bool stores normalized 0 or 1

    _Bool is a built-in type in C99 and later. When an integer, pointer comparison, or other scalar value is assigned to _Bool, C converts it to a normalized Boolean value: zero becomes 0, and any nonzero value becomes 1.

    This complete program assigns both zero and a nonzero integer to _Bool variables:

    • #include <stdio.h>
    • int main(void) {
    • _Bool enabled = 7;
    • _Bool disabled = 0;
    • printf(“%d %d\n”, (int)enabled, (int)disabled);
    • return 0;
    • }

    The output is 1 0. The explicit casts make the intended integer output clear. A _Bool value also undergoes integer promotion when passed to a variadic function such as printf, but the cast is a useful portable and readable pattern.

    The C bool type: stdbool.h aliases and complete declarations

    The C bool type is available through the standard header stdbool.h. In C99 through C17, that header defines bool as an alias-like macro for _Bool, while true and false represent 1 and 0. The header lets declarations read naturally without requiring a C++-style built-in bool keyword.

    This complete example declares and prints two Boolean values:

    • #include <stdbool.h>
    • #include <stdio.h>
    • int main(void) {
    • bool valid = true;
    • bool complete = false;
    • printf(“%s %s\n”, valid ? “true” : “false”, complete ? “true” : “false”);
    • return 0;
    • }

    Include stdbool.h before using bool, true, or false. Without the header, those names are not portable in traditional C versions that provide them as macros.

    How the bool type in C handles conditions and assignments

    The bool type in C is useful for storing a condition’s result, but an if statement does not require a Boolean object. C evaluates the controlling expression directly: integer zero is false, every nonzero integer is true, a null pointer is false, and every non-null pointer is true.

    For example, if (count) enters its block when count is nonzero. Similarly, if (buffer) enters its block when buffer points to an object. To normalize either value for storage, assign it to bool:

    • bool has_items = count;
    • bool has_buffer = buffer;

    Both assignments store only true or false. Comparisons and logical operators produce an integer result of 0 or 1, which can also be assigned directly to bool.

    Boolean functions, return values, and portable output

    A Boolean function should include stdbool.h and return bool when callers need a true-or-false result. A comparison such as n % 2 == 0 produces 1 or 0, and returning it from a bool function makes the interface explicit.

    • #include <stdbool.h>
    • #include <stdio.h>
    • bool is_even(int n) { return n % 2 == 0; }
    • int main(void) {
    • printf(“%s\n”, is_even(8) ? “true” : “false”);
    • return 0;
    • }

    The conditional operator converts the Boolean result into one of two string literals, making %s a portable way to print the words true and false. For numeric output, use printf(“%d\n”, (int)is_even(8)) to print 1 or 0.

  • Java Programs for Beginners: A Step-by-Step Practice Set

    Java Programs for Beginners: A Step-by-Step Practice Set

    These Java programs for beginners build from output and variables to input, conditions, loops, methods, arrays, and objects. Each example is a complete console program that can compile independently when saved using its public class name as the filename.

    Run a compiled class with java ClassName. Type the sample input when the program waits at the console.

    Java Programs for Beginners: Output, Variables, and Input

    Start with variables and output, then add console input with Scanner.

    FirstProgram.java: public class FirstProgram { public static void main(String[] args) { String language = "Java"; int lessons = 7; System.out.println(language + " lessons: " + lessons); } }

    Sample run: Input: none. Output: Java lessons: 7

    ReadName.java: import java.util.Scanner; public class ReadName { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Name: "); String name = input.nextLine(); System.out.println("Hello, " + name + "!"); input.close(); } }

    Sample run: Input: Mina. Output: Name: Mina, then Hello, Mina!

    Simple Java Programs: Conditions and Loops

    Conditions choose between outcomes. The remainder operator, %, checks whether a number divides evenly by two.

    EvenNumber.java: import java.util.Scanner; public class EvenNumber { public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Number: "); int number = input.nextInt(); if (number % 2 == 0) { System.out.println("Even"); } else { System.out.println("Odd"); } input.close(); } }

    Sample run: Input: 8. Output: Number: 8, then Even

    A for loop repeats a known number of times. Its counter starts at 1, continues through 5, and increases after each iteration.

    CountNumbers.java: public class CountNumbers { public static void main(String[] args) { for (int i = 1; i <= 5; i++) { System.out.println(i); } } }

    Sample run: Input: none. Output: 1 2 3 4 5, each number on its own line.

    Methods and Arrays in a Basic Java Program

    Methods package reusable behavior. Arrays store several values of the same type, and a loop can process every element.

    AddNumbers.java: public class AddNumbers { static int add(int first, int second) { return first + second; } public static void main(String[] args) { int total = add(4, 6); System.out.println("Total: " + total); } }

    Sample run: Input: none. Output: Total: 10

    ArrayTotal.java: public class ArrayTotal { public static void main(String[] args) { int[] scores = {4, 7, 9}; int total = 0; for (int score : scores) { total += score; } System.out.println("Total: " + total); } }

    Sample run: Input: none. Output: Total: 20

    A Small Class-Based Program That Creates an Object

    A class combines data and behavior. The constructor gives each object a title, and show displays it.

    BookDemo.java: class Book { String title; Book(String title) { this.title = title; } void show() { System.out.println("Book: " + title); } } public class BookDemo { public static void main(String[] args) { Book book = new Book("Java Basics"); book.show(); } }

    Sample run: Input: none. Output: Book: Java Basics

  • Binary Search in C with Iterative Code

    Binary Search in C with Iterative Code

    Binary search in C locates a target in a sorted array by repeatedly discarding half of the remaining candidates. This iterative implementation uses an overflow-resistant midpoint formula and returns a zero-based index or -1 when the target is absent.

    How does binary search in C work iteratively?

    For binary search C code, the loop tracks the active range with low and high. It checks the middle element, then moves the appropriate bound inward. The update must use mid + 1 or mid – 1 so the already-checked midpoint is not examined again.

    Complete program:

    #include <stdio.h>

    int binary_search(const int a[], int n, int target) {

    int low = 0, high = n – 1;

    while (low <= high) {

    int mid = low + (high – low) / 2;

    if (a[mid] == target) return mid;

    if (a[mid] < target) low = mid + 1;

    else high = mid – 1;

    }

    return -1;

    }

    int main(void) {

    int values[] = {3, 8, 12, 17, 21, 21, 34, 50};

    int n = sizeof values / sizeof values[0];

    int tests[] = {3, 50, 17, 21, 13};

    size_t count = sizeof tests / sizeof tests[0];

    for (size_t i = 0; i < count; i++) {

    int index = binary_search(values, n, tests[i]);

    printf(“target %d: %d\n”, tests[i], index);

    }

    return 0;

    }

    What do sorted input, bounds, and return values mean?

    The array must be sorted in ascending order. Without sorted input or another ordering guarantee, binary search cannot decide which half to discard; sort the data first when necessary.

    low is the first possible index, and high is the last possible index. The initial range is from 0 through n – 1. The midpoint is calculated as low + (high – low) / 2, rather than (low + high) / 2, reducing the risk of integer overflow for large indexes.

    This function returns the matching zero-based index immediately. If no candidate remains, low > high and the function returns -1. With duplicate values, it may return any matching occurrence; it does not promise the first or last duplicate.

    How do you trace and test found and absent targets?

    Using the sample array, trace a found target of 34:

    • low = 0, high = 7, mid = 3: value 17 is less than 34, so set low to 4.
    • low = 4, high = 7, mid = 5: value 21 is less than 34, so set low to 6.
    • low = 6, high = 7, mid = 6: value 34 matches, so return index 6.

    For an absent target of 13:

    • Midpoint 3 contains 17, so high becomes 2.
    • Midpoint 1 contains 8, so low becomes 2.
    • Midpoint 2 contains 12, so low becomes 3.
    • Now low is 3 and high is 2, so the function returns -1.

    The program tests the first element (3), last element (50), middle element (17), a duplicate (21), and an absent target (13). Expected results are indexes 0, 7, 3, 5, and -1 respectively for this implementation.

    How does C binary search compare with recursion, and what is its complexity?

    A recursive version makes the shrinking range explicit but adds function-call overhead. It uses the same midpoint calculation and return convention:

    int binary_search_recursive(const int a[], int low, int high, int target) {

    if (low > high) return -1;

    int mid = low + (high – low) / 2;

    if (a[mid] == target) return mid;

    if (a[mid] < target)

    return binary_search_recursive(a, mid + 1, high, target);

    return binary_search_recursive(a, low, mid – 1, target);

    }

    Call it with binary_search_recursive(values, 0, n – 1, target). Both iterative and recursive binary search run in O(log n) time because each comparison halves the remaining range. The iterative form uses O(1) extra space; recursion uses O(log n) stack space.

  • Bit Shifting in C: How > Move Bits

    Bit Shifting in C: How << and >> Move Bits

    Bit shifting in C and C++ moves an integer’s bits left or right with the << and >> operators. A C++ bit shift is easiest to verify with a fixed-width unsigned value: left shifts add zero bits on the right, while unsigned right shifts add zero bits on the left. The important boundaries are the promoted type’s width, the shift count, and whether the operand is signed.

    How does bit shifting in C use << and >>?

    The expression value << count moves each bit toward a more significant position. Bits that leave the type are discarded. The expression value >> count moves bits toward less significant positions. For an unsigned operand, zero bits enter from the left.

    For unsigned values, shifting left by n positions is equivalent to multiplying by 2n when the result remains within the available width. Shifting right by n positions is equivalent to dividing by 2n and discarding the remainder. A shift is not a rotation: discarded bits do not reappear at the other end.

    How do binary traces explain a C++ bit shift?

    These examples use 8-bit storage to make the movement visible. The binary notation shows the stored low eight bits.

    Left shift: uint8_t x = 0x2D; starts as 00101101. After x << 2, the trace is:

    00101101 << 2 = 10110100

    The value changes from decimal 45 to decimal 180. The two zeros entering on the right replace the two high bits that fall off the left.

    Unsigned right shift: uint8_t x = 0xB4; starts as 10110100. After x >> 2, the trace is:

    10110100 >> 2 = 00101101

    The result is decimal 45. In actual C and C++ expressions, small integer types undergo integer promotion first. If int can represent every uint8_t value, x is promoted to int; assigning the result back to uint8_t stores only the low eight bits.

    How do shifts create masks, fields, and powers of two?

    A shift creates a single-bit mask efficiently. With a 32-bit unsigned value, UINT32_C(1) << 5 produces 0x00000020, which selects bit 5. This represents 25. The count must stay within the valid range for the operand’s promoted type.

    To create a mask for the lowest four bits, use (UINT32_C(1) << 4) – 1, producing 0x0000000F. To extract an eight-bit field beginning at bit 8, use:

    (word >> 8) & UINT32_C(0xFF)

    The right shift moves the field to the low end, and the mask removes unrelated bits. To insert a bounded field, mask the source value before shifting it, then combine it with the destination using bitwise OR.

    How do signedness, width, and shift counts affect results?

    Both operands undergo integer promotion, and the result type is the promoted type of the left operand. Therefore, the width that controls a shift is not always the declared width. A uint8_t commonly promotes to int, so its shift count is checked against int’s width rather than eight bits. A uint32_t normally remains an unsigned 32-bit type because int cannot represent all its values.

    The shift count must be nonnegative and less than the bit width of the promoted left operand. A count equal to that width, or larger, produces undefined behavior in C and C++. Validate a runtime count before shifting; for a 32-bit value, a signed count must satisfy count >= 0 && count < 32.

    Unsigned left shifts have defined modulo behavior: high bits are discarded. Signed left shifts are riskier because a result that cannot be represented can cause undefined behavior. Convert to an appropriately sized unsigned type when that modulo behavior is intended.

    Right-shifting an unsigned value is logical and fills with zeros. Right-shifting a signed negative value is not a portable C shortcut: C makes that result implementation-defined, and language-version differences matter in C++. Use unsigned operands when the bit pattern, rather than an arithmetic sign, must be preserved.

  • JavaScript Regex Replace: Patterns, Flags, Groups, and Callbacks

    JavaScript Regex Replace: Patterns, Flags, Groups, and Callbacks

    JavaScript regex replace uses String.replace() to find a pattern and return a new string with replacement text. The original string remains unchanged. Use a plain search string for a literal match, or a regular expression when you need flags, groups, or pattern rules.

    For example, “red red”.replace(/red/, “blue”) returns “blue red”. The regex matches the first occurrence only because it does not include the global flag.

    JavaScript regex replace: Replace one match and return a new string

    A string search finds the exact sequence you provide: “cat”.replace(“cat”, “dog”) returns “dog”. A regex can express a broader rule, such as /cat/ or /cat[0-9]/.

    The replacement argument can be a fixed string. In “Order 42”.replace(/[0-9]+/, “complete”), the digits are replaced, producing “Order complete”. Without g, a regex replacement stops after the first match. This behavior applies even when several matches exist.

    Because replace() returns a string, assign its result when you need to keep it: const updated = source.replace(/old/, “new”). Calling the method does not modify source.

    Regex replacement in JavaScript: Use g and i to replace all matches

    The g flag means global matching. It makes the replacement continue through every match instead of stopping at the first one. For example, “Error error ERROR”.replace(/error/gi, “notice”) returns “notice notice notice”.

    The i flag makes matching case-insensitive. It allows /error/i to match error, Error, and ERROR. Combine flags when needed: /error/gi replaces all case variations.

    • /word/ replaces the first matching occurrence.
    • /word/g replaces every matching occurrence with matching case.
    • /word/i replaces the first case-insensitive occurrence.
    • /word/gi replaces every case-insensitive occurrence.

    A global regex does not change the original string, and the returned value is still a new string. Use a replacement string when every match should receive the same output.

    How do you replace text in JavaScript with captured groups?

    Capturing groups preserve parts of the match so the replacement can reuse them. In “Smith, Ada”.replace(/(\w+),\s*(\w+)/, “$2 $1”), group one captures Smith and group two captures Ada. The result is “Ada Smith”.

    Replacement references begin with a dollar sign. $1 inserts the first captured group, $2 inserts the second, and $& inserts the complete match. Add g when the same grouped structure can occur more than once: text.replace(/(\w+),\s*(\w+)/g, “$2 $1”).

    Use noncapturing parentheses, (?:…), for grouping that should not create a replacement reference. This keeps group numbers stable when the pattern becomes more complex.

    How do callbacks compute replacements and escape literal input?

    Pass a function instead of a replacement string when the output depends on the match. The callback receives the complete match first, followed by captured groups, the match position, and the complete input string.

    For example, “item-7 item-12”.replace(/item-(\d+)/g, (match, number) => “product ” + Number(number)) returns “product 7 product 12”. The callback can format values, perform calculations, or choose different output for each match.

    A regex pattern is different from escaped literal text. If user input is “a+b”, putting it directly into new RegExp(userInput, “g”) treats + as a regex operator rather than a literal character. For literal matching, use a string search or escape regex metacharacters first:

    const escaped = userInput.replace(/[.*+?^${}()|[\]\\]/g, “\\$&”);

    Then create the pattern with new RegExp(escaped, “g”). This preserves the input as literal text while still allowing global replacement.

  • Rounding Numbers in JavaScript: Math.round(), floor(), ceil(), and trunc()

    Rounding Numbers in JavaScript: Math.round(), floor(), ceil(), and trunc()

    To round a number in JavaScript, use Math.round() for the nearest integer: Math.round(4.6) returns 5. To round decimal places, multiply by a power of 10, round, then divide by the same factor. The method you choose matters for negative values, midpoint ties, and non-finite inputs.

    JavaScript rounding methods return numeric values. They do not change the original variable unless you assign the result back to it.

    How does rounding numbers in JavaScript work?

    Math.round(value) selects the nearest integer. When a value is exactly halfway between integers, JavaScript rounds toward positive infinity. Therefore, Math.round(3.5) returns 4, while Math.round(-3.5) returns -3, not -4.

    This comparison uses the same positive, negative, and midpoint inputs for each method. The values appear in this order: 3.7, -3.7, 3.5, -3.5.

    • Math.round(): 4, -4, 4, -3
    • Math.floor(): 3, -4, 3, -4
    • Math.ceil(): 4, -3, 4, -3
    • Math.trunc(): 3, -3, 3, -3

    How do you round a JavaScript number to an integer?

    To round a JavaScript number to an integer, choose the function that matches the desired direction:

    • Math.round(value): nearest integer, with midpoint ties toward positive infinity.
    • Math.floor(value): the next integer toward negative infinity. For example, Math.floor(-2.1) is -3.
    • Math.ceil(value): the next integer toward positive infinity. For example, Math.ceil(-2.1) is -2.
    • Math.trunc(value): removes the fractional portion toward zero. For example, Math.trunc(-2.9) is -2.

    Floor and truncation are not equivalent for negative values: Math.floor(-2.9) returns -3, whereas Math.trunc(-2.9) returns -2.

    How do you round decimal places in JavaScript?

    For a simple decimal-place calculation, scale the number before rounding:

    function roundTo(value, places) { const factor = 10 ** places; return Math.round(value * factor) / factor; }

    roundTo(12.346, 2) returns 12.35. With two decimal places, the factor is 100: JavaScript rounds 12.346 × 100 to 1235, then divides by 100. Replace Math.round() with Math.floor(), Math.ceil(), or Math.trunc() when directional rounding is required.

    Scaling also follows the selected method’s negative-number behavior. For example, scaling -12.346 by 100 and applying Math.round() produces -12.35; an exact negative midpoint follows Math.round’s tie rule.

    Why do negative values and floating-point numbers surprise you?

    Negative values expose the difference between direction and distance. Math.floor(-3.2) moves farther from zero to -4, while Math.trunc(-3.2) removes only the fraction and returns -3. Math.ceil(-3.2) also returns -3.

    Decimal scaling has a floating-point limitation. JavaScript stores ordinary numbers in binary floating-point, so many decimal fractions are represented slightly above or below their written value. For example, Math.round(1.005 * 100) / 100 can return 1 because the scaled value may be just below 100.5.

    For strict decimal rules, use integer units such as cents or decimal-aware arithmetic instead of assuming multiplication guarantees exact precision. Non-finite values pass through these methods: Math.round(NaN) returns NaN, Math.floor(Infinity) returns Infinity, Math.ceil(-Infinity) returns -Infinity, and Math.trunc(NaN) returns NaN.

  • JavaScript API Call with fetch(): GET and JSON POST Requests

    JavaScript API Call with fetch(): GET and JSON POST Requests

    Use fetch() to make a JavaScript API call with the browser’s built-in, promise-based request function. This guide shows how to call an API in JavaScript with async/await for GET and JSON POST requests.

    An API call from JavaScript returns a promise, so await keeps the control flow readable while the browser waits for a response.

    Build a JavaScript API call with fetch()

    fetch() starts a request and returns a promise that resolves to a Response object. The complete async GET function below adds URL parameters, checks response.ok before parsing, and rethrows failures so calling code can handle them.

    GET example: async function getUsers(limit, role) { try { const params = new URLSearchParams({ limit: String(limit), role }); const url = “https://api.example.com/users?” + params.toString(); const response = await fetch(url); if (!response.ok) { throw new Error(“GET failed: ” + response.status); } return await response.json(); } catch (error) { console.error(“Could not load users:”, error); throw error; } }

    GET is the default HTTP method, so this request does not need an options object. await fetch(url) waits for the response promise, while await response.json() waits for the separate promise that parses the response body.

    How to call an API in JavaScript with GET parameters

    Place query parameters after a question mark in the URL. URLSearchParams creates that query string and encodes spaces and special characters safely. In the example, limit and role become parameters such as ?limit=10&role=admin.

    Call the function with getUsers(10, “admin”). To set the method explicitly, pass a second argument to fetch(): fetch(url, { method: “GET” }). The server’s status is available through response.status, while response.ok is true only for successful 2xx responses.

    Send JSON with POST requests and headers

    Use POST when the request sends data to the server. Set the method to “POST”, identify the body as JSON with a Content-Type header, and convert the JavaScript object with JSON.stringify() before sending it.

    JSON POST example: async function createUser(user) { try { const response = await fetch(“https://api.example.com/users”, { method: “POST”, headers: { “Content-Type”: “application/json”, “Accept”: “application/json” }, body: JSON.stringify(user) }); if (!response.ok) { throw new Error(“POST failed: ” + response.status); } return await response.json(); } catch (error) { console.error(“Could not create user:”, error); throw error; } }

    For example, pass an object with createUser({ name: “Ada”, email: “[email protected]” }). The request headers tell the server how to interpret the body and what response format the client prefers.

    Handle network, HTTP, and parsing errors

    Handle these failures separately:

    • Network errors: fetch() rejects when the request cannot be completed, such as when the network is unavailable or the request is blocked. The surrounding try…catch handles that rejection.
    • HTTP errors: A 404 or 500 response does not automatically reject the fetch promise. The promise resolves normally, so check response.ok and throw an error when it is false.
    • Parsing errors: response.json() returns a promise and rejects when the body is not valid JSON. Using return await response.json() inside the try block sends that failure to catch.

    If an endpoint returns an empty or non-JSON body, use await response.text() instead of response.json().

  • Sort in JavaScript: Ascending and Descending Arrays

    Sort in JavaScript: Ascending and Descending Arrays

    sort in JavaScript uses the Array.prototype.sort() method. By default, it converts array elements to strings and orders their UTF-16 values, so string arrays often sort as expected but number arrays can produce surprising results.

    For numbers, pass a comparator: (a, b) => a – b sorts ascending, while (a, b) => b – a sorts descending. The same comparator pattern works for numeric properties on objects.

    How does sort in JavaScript behave by default for strings and numbers?

    Without a comparator, sort() compares string representations. For example, [‘pear’, ‘apple’, ‘orange’].sort() returns [‘apple’, ‘orange’, ‘pear’]. Uppercase and lowercase characters can appear in separate groups because their character codes differ.

    The same rule causes numeric errors. [10, 2, 1, 21].sort() becomes [1, 10, 2, 21], because the values are compared as ’10’, ‘2’, ‘1’, and ’21’. Use a numeric comparator whenever the array contains numbers. Default sorting is appropriate only when its string-based ordering matches the intended result.

    How does a JavaScript numeric sort handle ascending and descending values?

    A comparator receives two elements, a and b. A negative return value places a before b; a positive value places b first; zero treats them as equal. This return-value contract lets JavaScript calculate numeric order directly.

    For ascending order, subtract the second value from the first:

    const ascending = numbers.sort((a, b) => a – b);

    If a is smaller than b, the result is negative, so a moves earlier. If a is larger, the result is positive, so it moves later. This is the standard JavaScript numeric sort for low-to-high values.

    To sort descending in JavaScript, reverse the subtraction:

    const descending = numbers.sort((a, b) => b – a);

    Now a larger value produces a negative result and moves toward the start of the array. Both calls mutate numbers; use a copy when the original order matters.

    How do you sort objects by a property?

    For objects, the comparator should read the property used for ordering. This example sorts players by a numeric score from lowest to highest:

    players.sort((a, b) => a.score – b.score);

    For highest to lowest, switch the operands:

    players.sort((a, b) => b.score – a.score);

    String properties need a string comparator. For example, players.sort((a, b) => a.name.localeCompare(b.name)) orders names alphabetically according to the available locale rules. For descending names, compare b.name with a.name. Keep the property types consistent so the comparator returns reliable results.

    What changes when sort() mutates, and when should you use toSorted()?

    sort() changes the existing array and returns that same array. Declaring the array with const does not prevent this mutation; it only prevents assigning a different array to the variable.

    Copy the array before sorting when other code needs the original order:

    const ascending = […numbers].sort((a, b) => a – b);

    toSorted() provides the non-mutating alternative in modern JavaScript. It returns a new sorted array while leaving the source unchanged:

    const descending = numbers.toSorted((a, b) => b – a);

    Use sort() when changing the current array is intentional. Use toSorted(), or a spread copy followed by sort(), when immutability is required.