How do I convert a 64 bit steam ID to a 32 bit account ID? Steam says to take the first 32 bits of the number, but how do you do this in Node?
Do I need to use BigNumber to store the 64 bit int?
How do I convert a 64 bit steam ID to a 32 bit account ID? Steam says to take the first 32 bits of the number, but how do you do this in Node?
Do I need to use BigNumber to store the 64 bit int?
Share Improve this question edited Apr 24, 2014 at 4:37 Christian Stewart asked Apr 24, 2014 at 3:26 Christian StewartChristian Stewart 15.5k21 gold badges84 silver badges144 bronze badges 6-
2
Yes, you do need to use a BigNumber library. Javascript
number
s are all 64-bit IEEE floating point numbers. Notive that76561197991791363 === 76561197991791360
in Javascript. – Paul Commented Apr 24, 2014 at 3:34 -
@YTowOnt9 I just noticed that. Why is the last
3
in particular picked off? Is the number really one digit too large? – Christian Stewart Commented Apr 24, 2014 at 3:38 -
It's about the internal representation of doubles, similar to how
0.1 + 0.2 !== 0.3
. See this question. – Paul Commented Apr 24, 2014 at 3:40 - Numbers are stored in the IEEE 754 64-bit format – Paul Commented Apr 24, 2014 at 3:40
-
1
Where do you get
15762817
from? Unless I've screwed something up, neither the first or the second set of bits are equal to 15762817. – Qantas 94 Heavy Commented Apr 24, 2014 at 3:50
4 Answers
Reset to default 8To convert a 64 bit Steam ID to a 32 bit Account ID, you can just subtract 76561197960265728
from the 64 bit id.
This requires bigNumber in node:
bignumber = require("bignumber.js");
console.log(bignumber('76561197991791363').minus('76561197960265728'))
I had the same issue but didn't want to use any library like bignumber.js as my project was quite small and will be used in a web browser. In the end I came up with this elegant solution:
function steamID64toSteamID32 (steamID64) {
return Number(steamID64.substr(-16,16)) - 6561197960265728
}
How it works:
To get the lower 32 bits we need to convert the SteamID64 string to a number, but because JavaScript has a precision limit of 57 bits the SteamID64 will be erroneously rounded. The workaround is to truncate the leftmost digits to get a 16 digit number, which uses at most 54 bits and will therefore retain its precision in Javascript. This is acceptable because the leftmost digits es from the higher 32 bits which will be zeroed anyway, so nothing of value will be lost.
To zero the remaining higher bits we subtract the decimal number they're representing. If we assume that every SteamID64 we're converting to be in the public universe this decimal number will be constant and can be puted like this:
1. 0b00000001000100000000000000000001 0b00000000000000000000000000000000 = 76561197960265728
2. Number('76561197960265728'.substr(-16,16)) = 6561197960265728
Here's what I came up with. I started learning JavaScript yesterday (ing from a C++ background, not very accustomed to working without types), so correct me if I did something derpy with the language. I tested it with my own steam ID and it seems to work.
// NOTE: Functions can take in a steamID in its packed 64-bit form
// (munity ID starting with 765), its modern form with or without
// either or both brackets, and its legacy form. SteamID's that
// contain letters (e.g. STEAM_0... or [U:1...) are not case-sensitive.
// Dependencies: BigInteger library, available from http://silentmatt./biginteger/
// Global variable used by all conversion functions
var STEAM_BASELINE = '76561197960265728';
// IN: String containing a steamID in any of the 3 formats
// OUT: String containing the steamID as a munity ID (64-bit packed ID)
function ConvertToPacked(inputID)
{
var output = "unknown";
// From packed
if(inputID.match(/^765/) && inputID.length > 15)
{
output = inputID;
}
// From modern
else if(inputID.match(/^\[U:1:/i) || inputID.match(/^U:1:/i))
{
var numericPortion = inputID.replace(/^\[U:1:|^U:1:/i,'').replace(/\]/,'');
output = BigInteger.add(numericPortion, STEAM_BASELINE).toString();
}
// From legacy
else if(inputID.match(/^STEAM_0:[0-1]:/i))
{
var splitID = inputID.split(":");
var product = BigInteger.multiply(splitID[2],2);
var sum = BigInteger.add(product, STEAM_BASELINE);
output = BigInteger.add(sum, splitID[1]).toString();
}
return output;
}
// IN: String containing a steamID in any of the 3 formats
// OUT: String containing the steamID in the modern format (e.g. [U:1:123456])
function ConvertToModern(inputID)
{
var output = "unknown";
// From packed
if(inputID.match(/^765/) && inputID.length > 15)
{
output = "[U:1:" + BigInteger.subtract(inputID, STEAM_BASELINE).toString() + "]";
}
// From modern
else if(inputID.match(/^\[U:1:/i) || inputID.match(/^U:1:/i))
{
var numericPortion = inputID.replace(/^\[U:1:|^U:1:/i,'').replace(/\]/,'');
output = "[U:1:" + numericPortion + "]";
}
// From legacy
else if(inputID.match(/^STEAM_0:[0-1]:/i))
{
var splitID = inputID.split(":");
var numeric = BigInteger.add(BigInteger.multiply(splitID[2],2), splitID[1]);
output = "[U:1:" + numeric.toString() + "]";
}
return output;
}
// IN: String containing a steamID in any of the 3 formats
// OUT: String containing the steamID in the legacy format (e.g. STEAM_0:0:123456)
function ConvertToLegacy(inputID)
{
var output = "unknown"
// From packed
if(inputID.match(/^765/) && inputID.length > 15)
{
var z = BigInteger.divide(BigInteger.subtract(inputID, STEAM_BASELINE), 2);
var y = BigInteger.remainder(inputID, 2);
output = 'STEAM_0:' + y.toString() + ':' + z.toString();
}
// From modern
else if(inputID.match(/^\[U:1:/i) || inputID.match(/^U:1:/i))
{
var numericPortion = inputID.replace(/^\[U:1:|^U:1:/i,'').replace(/\]/,'');
var z = BigInteger.divide(numericPortion, 2);
var y = BigInteger.remainder(numericPortion, 2);
output = 'STEAM_0:' + y.toString() + ':' + z.toString();
}
// From legacy
else if(inputID.match(/^STEAM_0:[0-1]:/i))
{
output = inputID.toUpperCase();
}
return output;
}
Nodejs now supports BigInt as of Node version ~10. Additionally, MDN shows that BigInt is widely available in the browser.
This allows for simple subtraction:
// Note: Pass your number as a string to the BigInt constructor
// Number to subtract from your 64-bit SteamID
const steamBaseline = BigInt("76561197960265728");
// Your 64-bit SteamID
const steamId64 = BigInt("76561197991791363");
// Result
const steamId32 = (steamId64 - steamBaseline).toString();