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.
<!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>// 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); }
© 20072025 XoaX.net LLC. All rights reserved.