2

I'm trying to create two functions: the first one that converts a number (also float) to a hexadecimal string and the second one that does the vice versa.

This is my code:

function base10ToBase16(base10) {
  const precision = decimalsLength(base10)
  const multiplied = base10 * Math.pow(16, precision)
  const hexadecimal = multiplied.toString(16)
  
  if (isInteger(base10)) return hexadecimal
  return insertAt(hexadecimal, '.', hexadecimal.length - precision)
}

function base16ToBase10(base16) {
  const [integerPart, decimalPart] = base16.split('.')
  if (!decimalPart) return parseInt(integerPart, 16)
  return parseInt(integerPart, 16) + parseInt(decimalPart, 16) / Math.pow(16, decimalPart.length)
}

/////////////////////////
// Test
/////////////////////////
const numbers = [0, 0.5, 1, 0.8, 0.85, 0.855, 0.8555, 100, 255]
const hexes = numbers.map(n => base10ToBase16(n))
console.log(hexes)
console.log(hexes.map(h => base16ToBase10(h)))



/////////////////////////
// Utility functions
/////////////////////////
function insertAt(str, toAdd, position) {
  return `${str.slice(0, position)}${toAdd}${str.slice(position)}`
}

function isInteger(value) {
  return Number(value) === value && value % 1 === 0
}

function decimalsLength(value) {
  const [integerPart, decimalPart] = value.toString().split('.')
  return decimalPart ? decimalPart.length : 0
}

As you can see, hexes and numbers are not equals. Is there a way to do that? I read this question and I tried to follow their suggestions.

x00
  • 13,643
  • 3
  • 16
  • 40
whitecircle
  • 237
  • 9
  • 34
  • It looks like your integers are working fine, and the problem is only with your floats. – Dshiz Oct 25 '20 at 15:58
  • @Dshiz do you mean that `base10ToBase16` seems to work? Do you have some tips to make works also `base16ToBase10`? – whitecircle Oct 25 '20 at 16:26
  • `base16ToBase10` is correctly converting the integers back into integers, but not the floats back into floats as you can see with `NaN` in one of the results and the others are incorrect when compared to the original numbers. Unfortunately, I don't have any ideas on how to correct it. I just wanted to point it out. – Dshiz Oct 25 '20 at 16:31
  • One of the issues is that, when the base ten number is less than zero, you get an empty string for the units part. For example, `0.5` converts to `'.8'`. When you try to convert that back to base 10, `parseInt('',16)` gives `NaN`. – Ouroborus Oct 25 '20 at 18:03

1 Answers1

0

Your base16ToBase10 is fine. Your base10ToBase16 is wrong. Look at the snippet output.

function insertAt(str, toAdd, position) {
  return `${str.slice(0, position)}${toAdd}${str.slice(position)}`
}

function isInteger(value) {
  return Number(value) === value && value % 1 === 0
}

function decimalsLength(value) {
  const [integerPart, decimalPart] = value.toString().split('.')
  return decimalPart ? decimalPart.length : 0
}
function base10ToBase16(base10) {
  const precision = decimalsLength(base10)
  const multiplied = base10 * Math.pow(16, precision)
  const hexadecimal = multiplied.toString(16)
  
  if (isInteger(base10)) return hexadecimal
  return insertAt(hexadecimal, '.', hexadecimal.length - precision)
}

function base16ToBase10(base16) {
  const [integerPart, decimalPart] = base16.split('.')
  if (!decimalPart) return parseInt(integerPart, 16)
  return parseInt(integerPart, 16) + parseInt(decimalPart, 16) / Math.pow(16, decimalPart.length)
}

const numbers = [0, 0.5, 1, 0.8, 0.85, 0.855, 0.8555, 100, 255]
const wrong_hexes = numbers.map(base10ToBase16)
const hexes = numbers.map(n => n.toString(16))
console.log(wrong_hexes + "")
console.log(hexes + "")
console.log("hexes NOT eq wrong_hexes = ", hexes + "" !== 
wrong_hexes + "")

const roundtrip_numbers = hexes.map(base16ToBase10)
console.log(numbers + "")
console.log(roundtrip_numbers + "")
console.log("roundtrip_numbers eq numbers = ", roundtrip_numbers + "" === numbers + "")

Not really sure what are you trying to achieve with your own base10ToBase16 function. You already using toString(16) inside it. So the simplest way would be to use numbers.map(n => n.toString(16)) instead.

x00
  • 13,643
  • 3
  • 16
  • 40