11 ms·
JavaScript conceptually only has floats (ignoring big integers, which isn't what most people use for numbers), so any map of numbers to values is using a float
by chrisseaton 4y ago
JavaScript conceptually only has floats (ignoring big integers, which isn't what most people use for numbers), so any map of numbers to values is using a float key. You refer to that, but yeah they're all floats.
> it's generally difficult to get the same exact result every time on every system, due to rounding errors
Floating point arithmetic is 100% entirely deterministic - you don't just get different values randomly.
- cookiengineer 4y agoThis is so wrong ECMAScript does not have maps where keys can be integers and neither can keys be floats. Everything is a pointer to a value, and otherwise reflected with a symbol or string (which in return is a unique symbol). An object doesn't have object[1] because it is actually object[reference("1")] This way boxing and unboxing of arrays is much cheaper, due to the arrays not needing a resizing of their cells once datatypes change. (TypedArrays are optimized in a different manner, but we are speaking about the NaN use case, which implies either an Array or Object) There are dozens of talks about e.g. v8's hidden classes on youtube that show up this very mechanism. No idea where you got that float keys idea from.
- chrisseaton 4y ago> ECMAScript does not have maps where keys can be integers and neither can keys be floats. map = new Map(); map[1] = 3; map[1]; // 3 map[1.2] = 3.4; map[1.2]; // 3.4 typeof(map.keys().next().value); // "number" I'm not an expert in JavaScript. What am I missing?
- xg15 4y agoA nitpick: You're setting object properties on a Map object, which only works "accidentally" but does not make use of the map at all[1]. So in this case, it likely works because the numbers are converted to strings before being used as keys. But in general, using float keys does work - but can fail in unexpected ways due to rounding errors. E.g.: m = new Map(); m.set(0.3, "foo"); // --> Map { 0.3 → "foo" } m.get(0.3); // --> "foo" m.get(0.1 + 0.2); // --> undefined That's because 0.1 + 0.2 == 0.30000000000000004 in IEEE floats, which is != 0.3. [2] So using float keys which are derived from calculations and may contain non-integer numbers is a bad idea, because unless you have very good knowledge about floating point math, you can not easily predict what exact value the result of a calculation will be. [1] https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map#setting_object_properties https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refe... [2] https://stackoverflow.com/questions/8503157/ieee-754-floating-point-arithmetic-rounding-error-in-c-sharp-and-javascript https://stackoverflow.com/questions/8503157/ieee-754-floatin...
- chrisseaton 4y agoRight - should be using set and get - was written out without running it. But isn't this still a map that has float and integer keys? Why doesn't it count?
- matt_kantor 4y agoObject property names are always strings, even though you can set them via number literals (as the person you replied to said): const object = {} object[1] = 3 console.log(object["1"]) // 3 for (const key in object) { console.log(typeof key) // "string" } This is different from keys of the Map data structure, which are actually able to be any type of value (even silly stuff like other Maps).
- chrisseaton 4y agoI don't know - I think that proves what I said - map keys can be floats.
- matt_kantor 4y agoFor sure, I never disagreed with that (I even said "JavaScript maps absolutely can use numbers (or any type) as keys" in my other comment). But object property names cannot be floats (which is what your example was, despite them being properties of a Map object).
- xg15 4y agofrom what I got, it's a very stupid interaction of different javascript language features. Every object in JS has basic map functionality. Since version 1 of the language, you could always write things like: var o = new Object(); o["foo"] = "bar"; o["foo"] // --> "bar" However, this functionality is relatively limited: It only supports strings (and symbols) as keys and it interacts badly with other methods and properties which are part of the object. Hence why an explicit "Map" type was added to the language much later. The problem is, Maps are also objects, so they still inherit the "old" map functionality in addition to the new functionality. Those two systems are completely independent, even though they act on the same object. So writing mymap["foo"] = 1 and mymap.set("foo", 1) both store the mapping "foo" -> 1, but in completely different places. Only the second one will actually put it into the store of the map, while the first one will just add it as a generic object property. You can see it when trying to retrieve the value again: mymap["foo"] = 1 mymap["foo"]; // --> 1 mymap.get("foo"); // --> undefined likewise: mymap.set("bar", 1); mymap.get("bar"); // --> 1 mymap["bar"]; // --> undefined
- matt_kantor 4y agoWhat runtime did you use for that? JavaScript maps absolutely can use numbers (or any type) as keys, but that's not how its API works. Square brackets access object properties, but map entries are not stored like that, and that last `typeof` is `"undefined"` in every runtime I tried (not `"number"`). Try `map['set']` to see another example. Here's what I think you meant: const map = new Map(); map.set(1, 3); map.get(1); // 3 map.set(1.2, 3.4); map.get(1.2); // 3.4 typeof map.keys().next().value; // "number"
- chrisseaton 4y agoSquare brackets were a typo - I didn't run it I just wrote it off the top of my head. Doesn't your correct prove what I said though?
- matt_kantor 4y agoWe're certainly in agreement that cookiengineer's "ECMAScript does not have maps where keys can be integers and neither can keys be floats" assertion is dead wrong.
- cookiengineer 4y agoWhere does Map.__proto__ point to? There's your answer :) Everything in JS is an Object, therefore everything can have hashed keys. Including Arrays, because Array.__proto__ also points to Object.
- kleinsch 4y agoYou’re being pedantic. Nobody is talking about internal representations, they’re saying it’s literally possible to key into a map with a float, which is true.
- cookiengineer 4y agoNo it's not, because they are talking about keying via Number.prototype.toString(), which is not keying via float but via its string representation. And that's my point, it's even part of the ECMAScript spec. See 6.1.6.1 and 6.1.7.1 [1] Additionally, a proof you can quickly tryout: object={}; object[-0]=123; object[+0]; // returns object["0"]; If Object key were a Number type, it would not use Number.prototype.toString(). You can literally create your own datatype and override valueOf() and toString() to play with this. [1] https://262.ecma-international.org/13.0/ https://262.ecma-international.org/13.0/
- chrisseaton 4y agoWhat do you think is happening when you use set with a float on a map? How do you explain this? const map = new Map(); map.set(1, 3); map.get(1); // 3 map.set(1.2, 3.4); map.get(1.2); // 3.4 typeof map.keys().next().value; // "number" Where do you think ‘number’ comes from? Read the spec - it supports primitives for keys and it doesn’t stringing them. As others have said in this thread - you’re just wrong.
- deleted 4y ago[deleted]