Introduction
Converting a double (floating-point number) to a string is a fundamental operation across programming languages — needed for display, logging, serialization, and string concatenation. Each language has its own methods and formatting options for controlling decimal places, scientific notation, and locale-specific formatting (commas vs. periods as decimal separators).
Java
1double value = 3.14159;
2
3// String.valueOf() — most common
4String s1 = String.valueOf(value); // "3.14159"
5
6// Double.toString()
7String s2 = Double.toString(value); // "3.14159"
8
9// String.format() — with formatting
10String s3 = String.format("%.2f", value); // "3.14"
11String s4 = String.format("%.4f", value); // "3.1416" (rounded)
12String s5 = String.format("%e", value); // "3.141590e+00" (scientific)
13
14// Concatenation (implicit conversion)
15String s6 = "" + value; // "3.14159"
16
17// DecimalFormat for custom patterns
18import java.text.DecimalFormat;
19DecimalFormat df = new DecimalFormat("#.##");
20String s7 = df.format(value); // "3.14"
C#
1double value = 3.14159;
2
3// ToString() — default
4string s1 = value.ToString(); // "3.14159"
5
6// Format specifiers
7string s2 = value.ToString("F2"); // "3.14" (2 decimal places)
8string s3 = value.ToString("F4"); // "3.1416"
9string s4 = value.ToString("E2"); // "3.14E+000" (scientific)
10string s5 = value.ToString("N2"); // "3.14" (with thousand separators)
11string s6 = value.ToString("G"); // "3.14159" (general — shortest)
12
13// String interpolation
14string s7 = $"{value:F2}"; // "3.14"
15string s8 = $"{value:0.00}"; // "3.14"
16
17// Culture-specific
18using System.Globalization;
19string s9 = value.ToString("F2", CultureInfo.InvariantCulture); // "3.14"
20string s10 = value.ToString("F2", new CultureInfo("de-DE")); // "3,14"
Python
1value = 3.14159
2
3# str() — default
4s1 = str(value) # "3.14159"
5
6# f-string formatting
7s2 = f"{value:.2f}" # "3.14"
8s3 = f"{value:.4f}" # "3.1416"
9s4 = f"{value:e}" # "3.141590e+00"
10s5 = f"{value:010.2f}" # "0000003.14" (zero-padded)
11
12# format()
13s6 = format(value, ".2f") # "3.14"
14s7 = "{:.2f}".format(value) # "3.14"
15
16# repr() — full precision
17s8 = repr(value) # "3.14159"
18
19# Remove trailing zeros
20s9 = f"{value:.10f}".rstrip('0').rstrip('.') # "3.14159"
JavaScript / TypeScript
1const value = 3.14159;
2
3// String() or toString()
4const s1 = String(value); // "3.14159"
5const s2 = value.toString(); // "3.14159"
6
7// toFixed() — fixed decimal places
8const s3 = value.toFixed(2); // "3.14"
9const s4 = value.toFixed(4); // "3.1416"
10
11// toPrecision() — significant digits
12const s5 = value.toPrecision(3); // "3.14"
13
14// toExponential()
15const s6 = value.toExponential(2); // "3.14e+0"
16
17// Template literal
18const s7 = `${value}`; // "3.14159"
19
20// Intl.NumberFormat for locale-aware formatting
21const s8 = new Intl.NumberFormat('en-US', {
22 minimumFractionDigits: 2,
23 maximumFractionDigits: 2
24}).format(value); // "3.14"
C++
1#include <string>
2#include <sstream>
3#include <iomanip>
4#include <format> // C++20
5
6double value = 3.14159;
7
8// std::to_string() — default (6 decimal places)
9std::string s1 = std::to_string(value); // "3.141590"
10
11// stringstream with formatting
12std::ostringstream oss;
13oss << std::fixed << std::setprecision(2) << value;
14std::string s2 = oss.str(); // "3.14"
15
16// C++20 std::format
17std::string s3 = std::format("{:.2f}", value); // "3.14"
18std::string s4 = std::format("{:e}", value); // "3.141590e+00"
19
20// snprintf (C-style)
21char buf[32];
22snprintf(buf, sizeof(buf), "%.2f", value);
23std::string s5(buf); // "3.14"
Swift
1let value = 3.14159
2
3// String interpolation
4let s1 = "\(value)" // "3.14159"
5
6// String(format:) — printf-style
7let s2 = String(format: "%.2f", value) // "3.14"
8let s3 = String(format: "%.4f", value) // "3.1416"
9
10// NumberFormatter for locale-aware output
11let formatter = NumberFormatter()
12formatter.numberStyle = .decimal
13formatter.maximumFractionDigits = 2
14let s4 = formatter.string(from: NSNumber(value: value))! // "3.14"
Precision and Rounding Issues
1# Floating-point precision pitfall
2value = 0.1 + 0.2
3print(value) # 0.30000000000000004
4print(f"{value:.2f}") # "0.30" (formatted correctly)
5
6# Use Decimal for exact representation
7from decimal import Decimal
8d = Decimal("0.1") + Decimal("0.2")
9print(str(d)) # "0.3"
Common Pitfalls
Floating-point representation: 0.1 + 0.2 produces 0.30000000000000004 in most languages. Always use format specifiers (.2f) for display rather than raw toString().
Locale issues: In some locales, the decimal separator is a comma (3,14 in German). Use InvariantCulture (C#), Locale.US (Java), or equivalent when generating machine-readable output.
to_string precision in C++: std::to_string(3.14) produces "3.140000" (6 decimal places). Use std::format or stringstream for custom precision.
toFixed returns a string: In JavaScript, (3.14).toFixed(2) returns the string "3.14", not a number. Calling Number(x.toFixed(2)) converts back.
Scientific notation for extreme values: Very large or very small doubles may default to scientific notation ("1e+20"). Use fixed-point format specifiers to force decimal notation.
Summary
Java: String.valueOf(d) or String.format("%.2f", d)
C#: d.ToString("F2") or $"{d:F2}"
Python: f"{d:.2f}" or str(d)
JavaScript: d.toFixed(2) or String(d)
C++: std::to_string(d) or std::format("{:.2f}", d) (C++20)
Always use format specifiers for display to control decimal places and avoid floating-point artifacts