Core JavaScript

IEEE Floating-Point Representations

The JavaScript code example demonstrates how bit are arranged and set for the 32 bit and 64 bit IEEE floating point formats. The top selector allows for the selection of a few numerical values and various special values such as infinity. The second input allows for the entry of numerical values. Once a value is set, its corresponding IEEE representations are shown below the for both the 32 and 64 bit fomats. Additionally, individual bits may be switched by clicking the checkboxes under the bit values.

The bit values are displayed in two formats. The first format shows clickable checkboxes paired with the sign bit, exponent and mantissa; note that the expoenents have biases of 127 and 1023, which are subtracted from the exponent to allow them to vary between positive and negative values. The mantissa has an implied 1 at the beginning, except for special values like zero.

FloatingPointFormat.html

<!DOCTYPE	html>
<html>
	<head>
		<title>XoaX.net's	Javascript</title>
		<script	type="text/javascript" src="FloatingPointFormat.js"></script>
		<style>
			body {
				background-color:white;
			}
			.cType {
				border:1px #F0F0F0 solid;
				width:fit-content;
				float:left;
				clear:both;
			}
			.cBits {
				background-color:#D0D0D0;
				width:fit-content;
				float:left;
				margin: 0px;
			}
			.cDigit	{
				font-family:monospace;
				color:green;
				margin-left:auto;
				margin-right:auto;
				width:fit-content;
			}
			.cCheck	{
				margin-left:auto;
				margin-right:auto;
				width:fit-content;
			}
			.cBitGroup {
				border:	1px	lightgray	solid;
				background-color:#F0F0F0;
				float:left;
				margin-right:5px;
			}
			.cCenter {
				margin-left:auto;
				margin-right:auto;
				width:fit-content;
			}
			.cActualBits {
				font-family:monospace;
				background-color:white;
				color:green;
			}
		</style>
	</head>
	<body	onload="Initialize()">
	</body>
</html>

FloatingPointFormat.js

// Precision arrays
const ksaPrecision = ["Single", "Double"];
const kiaBitCounts = [32, 64];
const kiaMaxByteIndex = [3, 7];
// These are the bits elements in the web page
var gqaEditBits = [];
var gqaValues = [];
const ksaBitSets = ["Sign", "Exponent", "Mantissa"];
const kiaaBitSetSizes = [[1, 8, 23], [1, 11, 52]];

function SelectFixedValue() {
	// Blank out the input first
	document.getElementById("idInputValue").value = null;
	var sValue = document.getElementById("idSelectedValue").value;
	if (sValue == "zero") {
		gqaValues[0][0] = 0;
		gqaValues[1][0] = 0;
	} else if (sValue == "one"){
		gqaValues[0][0] = 1;
		gqaValues[1][0] = 1;
	} else if (sValue == "two"){
		gqaValues[0][0] = 2;
		gqaValues[1][0] = 2;
	} else if (sValue == "infinity"){
		gqaValues[0][0] = Number.POSITIVE_INFINITY;
		gqaValues[1][0] = Number.POSITIVE_INFINITY;
	} else if (sValue == "-infinity"){
		gqaValues[0][0] = Number.NEGATIVE_INFINITY;
		gqaValues[1][0] = Number.NEGATIVE_INFINITY;
	} else if (sValue == "NaN"){
		gqaValues[0][0] = Number.NaN;
		gqaValues[1][0] = Number.NaN;
	} else if (sValue == "epsilon"){
		gqaValues[0][0] = Number.EPSILON;
		gqaValues[1][0] = Number.EPSILON;
	} else if (sValue == "max"){
		gqaValues[0][0] = Number.MAX_VALUE;
		gqaValues[1][0] = Number.MAX_VALUE;
	} else if (sValue == "min"){
		gqaValues[0][0] = Number.MIN_VALUE;
		gqaValues[1][0] = Number.MIN_VALUE;
	} else if (sValue == "max safe int"){
		gqaValues[0][0] = Number.MAX_SAFE_INTEGER;
		gqaValues[1][0] = Number.MAX_SAFE_INTEGER;
	} else if (sValue == "min safe int"){
		gqaValues[0][0] = Number.MIN_SAFE_INTEGER;
		gqaValues[1][0] = Number.MIN_SAFE_INTEGER;
	} else {
		return;
	}
	// Finally, update the values
	UpdateActualBitsAndValuesFromValues();
	// Set the selectable bits from the values
	UpdateEditBitsFromValues();
}

function SetInputValue() {
	// Blank out the selector
	document.getElementById("idSelectedValue").value = "";
	var sValue = document.getElementById("idInputValue").value;
	gqaValues[0][0] = sValue;
	gqaValues[1][0] = sValue;
	// Finally, update the values
	UpdateActualBitsAndValuesFromValues();
	// Set the selectable bits from the values
	UpdateEditBitsFromValues();
}

function UpdateActualBitsAndValuesFromValues() {
	var qActualBitsDivs = document.getElementsByClassName("cActualBits");
	var qActualValuesSpans = document.getElementsByClassName("cActualValues");
	for (var i = 0; i < 2; ++i) {
		qActualBitsDivs[i].innerHTML = GetDisplayBits(i);
		qActualValuesSpans[i].innerHTML = gqaValues[i];
	}
}

function GetDisplayBits(iPrecisionIndex) {
	var sBits = "";
	const kuiaArray = new Uint8Array(gqaValues[iPrecisionIndex].buffer);
	for (var i = 0; i < kiaBitCounts[iPrecisionIndex]; ++i) {
		sBits += ((((kuiaArray[Math.floor(i/8)] >> (7 - (i % 8))) & 1) == 1) ? "1" : "0");
		if ((i % 8) == 7) {
			sBits += " ";
		}
	}
	return sBits;
}

function UpdateEditBitsFromValues() {
	// Iterate over both precision values: 32 bits and 64 bits
	for (var i = 0; i < 2; ++i) {
		const kuiaArray = new Uint8Array(gqaValues[i].buffer);
		for (var iBitIndex = 0; iBitIndex < kiaBitCounts[i]; ++iBitIndex) {
			var iBytePos = (kiaMaxByteIndex[i] - Math.floor(iBitIndex/8));
			var iBitPos = (7 - (iBitIndex % 8));
			var iBitValue = ((kuiaArray[iBytePos] >> iBitPos) & 1);
			// Set the digit and corresponding checkbox
			if (iBitValue == 1) {
				gqaEditBits[i][iBitIndex].children[0].innerHTML = "1";
				gqaEditBits[i][iBitIndex].children[1].checked = true;
			} else {
				gqaEditBits[i][iBitIndex].children[0].innerHTML = "0";
				gqaEditBits[i][iBitIndex].children[1].checked = false;
			}
		}
	}
}

function CheckboxClicked() {
	// Blank out the input first
	document.getElementById("idInputValue").value = null;
	// Blank out the selector
	document.getElementById("idSelectedValue").value = "";
	// Find out if this is the 32 bit or 64 bit value
	const kqThis = window.event.currentTarget;
	if (kqThis.parentElement) {
		var iPrecisionIndex = 2;
		if (kqThis.parentElement.parentElement.parentElement.id == 'id32') {
			iPrecisionIndex = 0;
		} else if (kqThis.parentElement.parentElement.parentElement.id == 'id64') {
			iPrecisionIndex = 1;
		}
		// Set the value corresponding to the checkbox
		if (kqThis.checked) {
			kqThis.parentElement.children[0].innerHTML = "1";
		} else {
			kqThis.parentElement.children[0].innerHTML = "0";
		}
		for (var i = 0; i < kiaBitCounts[iPrecisionIndex]; ++i) {
			// Log the index of the changed bit
			if (kqThis.parentElement === gqaEditBits[iPrecisionIndex][i]) {
				console.log("Bit index = "+i);
			}
			// Change the value first
			var iBitValue = ((gqaEditBits[iPrecisionIndex][i].children[0].innerHTML == "0") ? 0 : 1);
			// Set the bits of the number
			SetActualBit(iPrecisionIndex, i, iBitValue);
		}
		UpdateActualBitsAndValuesFromValues();
	}
}

// Set the bits via a function that takes a position and a bit value
function SetActualBit(iPrecisionIndex, iPosition, iBitValue) {
	const kuiaArray = new Uint8Array(gqaValues[iPrecisionIndex].buffer);
	var iShiftedBit = ((iBitValue & 1) << (7 - (iPosition % 8)));
	var iBitMask = (1 << (7 - (iPosition % 8)));
	var iMaxByte = kiaMaxByteIndex[iPrecisionIndex];
	var iByteIndex = (iMaxByte - Math.floor(iPosition/8));
	// Byte order it reversed because bytes are little-endian
	// And with the complement removes the valued bit, which we add back in.
	kuiaArray[iByteIndex] = ((kuiaArray[iByteIndex] & (~iBitMask)) + iShiftedBit);
}

function ConstructBitGroups(qContainer) {
	var qSetValuesDiv = document.createElement("div");
	qSetValuesDiv.style.width = "600px";
	qSetValuesDiv.style.padding = "20px 5px";
	qSetValuesDiv.style.backgroundColor = "#F0F0F0";
	qSetValuesDiv.style.border = "1px	lightgray	solid";
	qContainer.append(qSetValuesDiv);
	// Add in a selector to allow the selection of special values
	var qValueSelector = document.createElement("select");
	qValueSelector.id = "idSelectedValue";
	qValueSelector.onchange = SelectFixedValue;
	// Add option values that can be selected
	var saOptionValues = ["","zero", "one", "two", "infinity", "-infinity", "NaN", "epsilon", "max", "min", "max safe int", "min safe int"];
	for (var i = 0; i < saOptionValues.length; ++i) {
		var qSelectOption = document.createElement("option");
		qSelectOption.value = saOptionValues[i];
		qSelectOption.innerHTML = saOptionValues[i];
		qValueSelector.append(qSelectOption);
	}
	// Add a label for the selector
	var qValueSelectorLabel = document.createElement("label");
	qValueSelectorLabel.for = "idSelectedValue";
	qValueSelectorLabel.innerHTML = "<b>Select a Fixed Value</b>: ";
	qSetValuesDiv.append(qValueSelectorLabel);
	var qLineBreak = document.createElement("br");
	qSetValuesDiv.append(qValueSelector);
	qSetValuesDiv.append(qLineBreak);
	var qHorizRule = document.createElement("hr");
	qSetValuesDiv.append(qHorizRule);
	// Add in an input element
	var qInputElement = document.createElement("input");
	qInputElement.type = "number";
	qInputElement.id = "idInputValue";
	qInputElement.onchange = SetInputValue;
	var qInputLabel = document.createElement("label");
	qInputLabel.for = "idInputValue";
	qInputLabel.innerHTML = "<b>Enter a Value</b>: ";
	qSetValuesDiv.append(qInputLabel);
	qLineBreak = document.createElement("br");
	qSetValuesDiv.append(qInputElement);
	qSetValuesDiv.append(qLineBreak);
	// Loop over the two different precision values 32 bit and 64 bit.
	for(var i = 0; i < ksaPrecision.length; ++i) {
		// Allocate data values
		gqaEditBits[i] = new Array();
		const kui8aArray = new Uint8Array(4*(i+1));
		if (i == 0) {
			gqaValues[i] = new Float32Array(kui8aArray.buffer);
		} else {
			gqaValues[i] = new Float64Array(kui8aArray.buffer);
		}
		// Start adding elements
		var qTypeDiv = document.createElement("div");
		qTypeDiv.classList.add("cType");
		qTypeDiv.id = "id"+kiaBitCounts[i];
		qContainer.append(qTypeDiv);
		// Add the type label
		var qTypeLabelDiv = document.createElement("h3");
		qTypeLabelDiv.classList.add("cCenter");
		qTypeLabelDiv.innerHTML = ksaPrecision[i]+" Precision "+kiaBitCounts[i]+ " Bits";
		qTypeDiv.append(qTypeLabelDiv);
		var iBitIndex = 0;
		// Create the bit groups
		for(var j = 0; j < ksaBitSets.length; ++j) {
			var qBitSetDiv = document.createElement("div");
			qBitSetDiv.classList.add("cBitGroup");
			qBitSetDiv.id = "id"+ksaBitSets[j]+kiaBitCounts[i];
			qTypeDiv.append(qBitSetDiv);
			// Add the set label
			var qBitSetLabelDiv = document.createElement("p");
			qBitSetLabelDiv.classList.add("cCenter");
			qBitSetLabelDiv.innerHTML = ksaBitSets[j];
			qBitSetDiv.append(qBitSetLabelDiv);
			// Add the set bit count label
			var qBitSetBitCountDiv = document.createElement("p");
			qBitSetBitCountDiv.innerHTML = kiaaBitSetSizes[i][j]+" bit"+(kiaaBitSetSizes[i][j] > 1? "s":"");
			qBitSetDiv.append(qBitSetBitCountDiv);
			for(var k = 0; k < kiaaBitSetSizes[i][j]; ++k) {
				var qBitDiv = document.createElement("div");
				qBitDiv.classList.add("cBits");
				qBitDiv.id = "id"+ksaBitSets[j]+kiaBitCounts[i]+"Bit"+k;
				qBitSetDiv.append(qBitDiv);
				// Digit Div
				var qDigitDiv = document.createElement("div");
				qDigitDiv.classList.add("cDigit");
				qDigitDiv.id = "id"+kiaBitCounts[i]+(iBitIndex <= 9? "0":"")+iBitIndex;
				qDigitDiv.innerHTML = "0";
				qBitDiv.append(qDigitDiv);
				// Check
				var qInput = document.createElement("input");
				qInput.classList.add("cCheck");
				qInput.id = "idCheck"+kiaBitCounts[i]+(iBitIndex <= 9? "0":"")+iBitIndex;
				qInput.type = "checkbox";
				qInput.checked = false;
				qInput.onclick = CheckboxClicked;
				qBitDiv.append(qInput);
				// Add the element to the array
				gqaEditBits[i][iBitIndex] = qBitDiv;
				++iBitIndex;
			}
		}
		// Display the actual bits as a byte array
		var qHR = document.createElement("hr");
		qHR.style.clear = "both";
		qTypeDiv.append(qHR);
		var qActualBitsLabel = document.createElement("p");
		qActualBitsLabel.innerHTML = "Actual Memory Bits";
		qTypeDiv.append(qActualBitsLabel);

		// Display the actual bits
		var qActualBitsDiv = document.createElement("div");
		qActualBitsDiv.classList.add("cActualBits");
		qActualBitsDiv.innerHTML = GetDisplayBits(i);
		qTypeDiv.append(qActualBitsDiv);
		
		// Display the values
		var qValueHR = document.createElement("hr");
		qValueHR.style.clear = "both";
		qTypeDiv.append(qValueHR);
		var qActualValuesDiv = document.createElement("div");
		var qActualValuePara = document.createElement("p");
		qActualValuePara.innerHTML = "Actual Value: ";
		var qActualValueSpan = document.createElement("span");
		qActualValueSpan.classList.add("cActualValues");
		qTypeDiv.append(qActualValuesDiv);
		qActualValuesDiv.append(qActualValuePara);
		qActualValuePara.append(qActualValueSpan);
	}
}

function Initialize() {
	// Get the body element
	var qBody = document.getElementsByTagName("body")[0];

	// Create and insert the HTML elements
	ConstructBitGroups(qBody);
}
 

Output

 
 

© 2007–2025 XoaX.net LLC. All rights reserved.