Changing floating point numbers to text in JavaScript

I'm looking for an efficient way to store an array of THREE.Vector3 objects in local storage using JavaScript. Since JavaScript operates with strings, I need to convert a 32-bit float to a string using the best bit ratio possible, ideally equating 32-bit float to 4 * 8 bits, similar to how it's done in C++.

However, there are two main issues I'm facing. Firstly, JavaScript strings are encoded in UTF-8 which includes some padding.

http://en.wikipedia.org/wiki/UTF-8

Secondly, the code I'm currently using converts 0 to '' which then gets omitted, leading to unreliable byte length conversion.


var float2str = function(num) {
    var bytestream = new Array();
    var view = new DataView(new ArrayBuffer(4));
    view.setFloat32(0, num);

    bytestream.push(view.getUint8(0));
    bytestream.push(view.getUint8(1));
    bytestream.push(view.getUint8(2));
    bytestream.push(view.getUint8(3));
    return String.fromCharCode(view.getUint8(0), view.getUint8(1), view.getUint8(2), view.getUint8(3));
}

var str2float = function(str) {
    var bytestream = unpack(str);
    var view = new DataView(new ArrayBuffer(4));
    view.setUint8(0, bytestream[0]);
    view.setUint8(1, bytestream[1]);
    view.setUint8(2, bytestream[2]);
    view.setUint8(3, bytestream[3]);
    return view.getFloat32(0);
}

Thank you!

Answer №1

To ensure the string value of unsigned 8-bit integers is printable, it's crucial to consider the range of ASCII values. If the numbers are too small or too large, they may result in unprintable characters. One approach to address this issue is to use 4-bit values from the float and adjust them into the printable range by adding an offset of +32. Here is a method that implements this:

var offset = 33;

var floatToStr = function(num){
    var view = new DataView(new ArrayBuffer(4));
    view.setFloat32(0,num);

    var fourbits = [];
    for ( var i = 0; i < 4; i++ ){
        // split each byte into two 4-bit values
        fourbits.push(view.getUint8(0) >> 4);
        fourbits.push(view.getUint8(0) & 15);
    }

    for ( var i = 0; i < 8; i++ ){
        // construct a string with adjusted four-bit values
        fourbits[i] = String.fromCharCode(offset+fourbits[i]);
    }
    return fourbits.join('');

};

var strToFloat = function(str){
    var bytestream = str;
    var view = new DataView(new ArrayBuffer(4));

    for(var i = 0; i < 4; i++){
        // convert the characters back into bytes.
        view.setUint8(i, ((bytestream[i*2].charCodeAt() - offset) << 4) + bytestream[i*2+1].charCodeAt() - offset);
    }

    return view.getFloat32(0);
};

console.log(floatToStr('2.251')); // "%!\"!\"!'#"
console.log(strToFloat(floatToStr('2.251'))); // 2.250999927520752

This solution aims to provide a helpful way to handle the conversion process.

Answer №2

To achieve compression, utilize base64 encoding method. This technique transforms 6 bits into a printable ASCII character at a time (which remains the same in UTF-8). Consequently, only 5.33 bytes are actually required for one float when using this approach (note that it is not equivalent to 6 bytes as long as you encode the array collectively rather than individual floats), resulting in some space efficiency.

For direct conversion from ArrayBuffer to base64 string, refer to this ready-made function (credit to original author): https://gist.github.com/958841

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Which is the better option for setting a title: using .prop or .attr?

I came across a comment that mentioned The suggestion was to utilize the .prop() method instead of .attr() when setting the "title" property in jQuery versions 1.6 or newer. Could someone provide an explanation for this recommendation? ...

Cloning a file input does not retain the uploaded file in the cloned input. Only the original input retains the uploaded file

Whenever I duplicate an input type file, I encounter an issue where the uploaded file from the duplicated input is also linked to the original input. It seems like the duplicate input is somehow connected to and taking files for the original one. This is ...

Remove any list items that do not possess a particular class

My ul list contains several lis, and I need to remove all li elements that do not have children with the class noremove. This is the original HTML: <ul> <li>Item 1</li> <li>Item 2 <ul> <li>I ...

Finding unique data stored in separate JSON files and loading them individually may require using different methods for

I have two JSON files named marker.json and marker.json0 that contain different latitude and longitude coordinates. To load them, I need to rename .json0 to .json (and vice versa), so that the new data from marker.json0 now resides in marker.json. This way ...

What could be causing my button to not display within the li element?

I need to insert a delete button (deleteButton) into an <li></li> element that is created and added before the <ol> Here is my code: let eventList = []; const inputBox = document.querySelector('.input-field'); const submit = ...

Creating subpages using IDs can be accomplished by following these simple steps

Currently, I am in the process of developing a website that contains a plethora of information, specifically news articles. Each news article on my site features an introduction and a header. Upon clicking on a particular news article, the full content is ...

Using arrow brackets in Flux Dispatcher code written in JavaScript

While exploring the source code on GitHub for the Flux Dispatcher, I came across an interesting syntax using angle brackets: class Dispatcher<TPayload> { .... } I'm curious to know if this is a new feature of the language or perhaps a subset l ...

The background image fails to load in ReactJS application

Usually, I have no trouble finding solutions to my problems, but this time I'm really stuck - and I apologize in advance if my question seems silly or trivial. I am currently working on a simple React app where I need to set a background image for th ...

Can I add the object to the DOM and hold off on executing any events until the next

Just came across this intriguing interview question (shown below). Could someone please provide an explanation of the question and then offer a solution? Develop a function that takes an object and adds it to the DOM, ensuring that events are stored unt ...

Unlimited scrolling with React and Meteor

Struggling with implementing infinite scrolling in my Meteor and React app. Even after trying multiple npm and Meteor packages, I still can't get it to work. The "createContainer" function subscribes to the entire dataset of "links", but I only want t ...

Setting radio button values according to dropdown selection - a beginner's guide

I am trying to dynamically set the default values of radio buttons based on the selection made in a drop-down menu. For example, if option A or B is chosen, I want the radio button value to default to "Summary", and if option C is chosen, I want the value ...

Using Javascript to extract and organize JSON arrays from various sets of checkboxes

Is there a way to automatically create an array of multiple groups of arrays like this: arr = {arr1:{index:value, index2:value2}, arr2:{index,value, index2:value2}}; The order is based on groups of checkboxes in HTML (see example below): <div class=& ...

Utilize ModifyDOM to erase text triggered by selecting a radio button

I have created a form that includes four radio buttons along with a reset button to clear the form. When a radio button is selected, information is displayed using "displayText". I am looking to add an onclick handler to trigger a function that will delete ...

Is there a way to bring this specific function into a separate file?

There's a common practice where anonymous functions (arrow functions) are exported as default from one file. My question is, how can this be imported and used in another file? If I export the following function that returns an Object containing store ...

Create a dynamic form using JSON data and the Material UI library

Looking for assistance in creating a dynamic form on Next.js by parsing JSON files and generating the required components from the JSON data. Additionally, seeking guidance on utilizing the Material UI library for styling. Any examples or help would be g ...

CalendarExtender displaying an incorrect date selection, potentially linked to time zone issues

I'm encountering an issue on a webpage where I have a TextBox and a CalendarExtender. The purpose of this setup is to help me determine the selected date. However, it's showing the wrong date. <asp:TextBox ID="tbEffectiveDate" runat="server" ...

The object's property is currently displaying as unidentifiable

Is there a way to associate an empty array with an object property so it can be accessed later using dot notation? http://jsfiddle.net/bobbyrne01/ckdfyfxp/ var AJAX_Utils_AddressBook = { contacts: null }; var contact = []; AJAX_Utils_AddressBook.con ...

Transmit variables to ajax callback function

I'm a beginner when it comes to AJAX, so I'm using 'Jquery Form' to help me out. I'm trying to pass the entry and path variables to the success callback. var optionsUpdate = { data: { entry: entry, path: path }, success: ...

Using Javascript to swap background images, ensuring that the initial image is shown only once

I have a query regarding the background image rotation on my HTML page. I am currently using the code below to change the background image, but I want the first image to be displayed only once while the rest continue rotating. Can anyone provide guidance o ...

Interacting with local data using Express server

I am currently in the process of developing a web application for my web art class using Node.js with npm and Express. The concept behind the site is to have the entire body colored in one solid color, but allow users to text a hexcode/CSS color to a Twili ...