Why are doubles printed differently in dictionaries?
As already mentioned in the comments, a Double
cannot store
the value 1.1
exactly. Swift uses (like many other languages)
binary floating point numbers according to the IEEE 754
standard.
The closest number to 1.1
that can be represented as a Double
is
1.100000000000000088817841970012523233890533447265625
and the closest number to 2.3
that can be represented as a Double
is
2.29999999999999982236431605997495353221893310546875
Printing that number means that it is converted to a string with
a decimal representation again, and that is done with different
precision, depending on how you print the number.
From the source code at HashedCollections.swift.gyb one can see that the description
method ofDictionary
uses debugPrint()
for both keys and values,
and debugPrint(x)
prints the value of x.debugDescription
(if x
conforms to CustomDebugStringConvertible
).
On the other hand, print(x)
calls x.description
if x
conforms
to CustomStringConvertible
.
So what you see is the different output of description
and debugDescription
of Double
:
print(1.1.description) // 1.1
print(1.1.debugDescription) // 1.1000000000000001
From the Swift source code one can see
that both use the swift_floatingPointToString()
function in Stubs.cpp, with the Debug
parameter set to false
and true
, respectively.
This parameter controls the precision of the number to string conversion:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
For the meaning of those constants, see std::numeric_limits:
digits10
– number of decimal digits that can be represented without change,max_digits10
– number of decimal digits necessary to differentiate all values of this type.
So description
creates a string with less decimal digits. That
string can be converted to a Double
and back to a string giving
the same result.debugDescription
creates a string with more decimal digits, so that
any two different floating point values will produce a different output.
Why does double backslash not work in python dictionary
How do you verify that it does not work?
Using the print function you can see that it does exactly what you expect:
x = {
'myserver' : {
'DSN': 'servername',
'DATABASE': 'mydatabase',
'UID': 'myusername',
'PWD': 'my\\password'
}
}
print(x)
print(x['myserver']['PWD'])
Outputs:
{'myserver': {'DSN': 'servername', 'DATABASE': 'mydatabase', 'UID': 'myusername', 'PWD': 'my\\password'}}
and
my\password
Trying to add data to different dictionaries and print one then another
A few different problems here. First, what is your dict named (dict
isn't instantiated anywhere that I can see)? You don't define it as far as I can see. As for update, the parameter is not a string and there's no reason to use format; the keys in the object can be strings, which is likely why you're confused, but those commas aren't wrapped in a string. I also don't see why you're using update here rather than just setting the properties values in general.
Finally, as with the other comments, I'm also not clear on what you want the dict to look like after, or why you'd separate highs and lows into separate dictionaries.
I'd probably do this:
def readTempData(filename):
with open(filename, 'r') as f:
data = {}
for line in f.readlines():
day, high, low = line.split(',')
high = int(high)
low = int(low)
day = int(day)
data[day] = {'high': high, 'low': low}
print(data)
readTempData(input("Enter file name:"))
You then can see the day as the key, with the high and low on the day easily accessible. If you want a seperate dict of high / low, you should clarify what you want as a key. You could also use a list of dictionaries which contain the day, high, and low.
For example, to access the high temperature on day 3
:
data[3]['high']
Strange output for same Double value
As in answer explained by @MartinR, Why are doubles printed differently in dictionaries?
It is clear that 1.1200000000000001, is the double precision value of 1.12.
While you are trying to print foo object, print(foo)
object is getting printed along with its enclosed information in which number
holds the double precisied value of 1.21
Whereas, when you directly print(foo.number)
, then string representation of foo.number
is getting printed which is actually 1.21
How to create a double dictionary in Python?
You could try this:
In [17]: results = {}
In [18]: for k, v in names.iteritems():
results[k] = {v: dates.setdefault(k, '')}
....:
....:
In [20]: results
Out[20]:
{'George': {'march': '21/02'},
'Mary': {'february': '2/02'},
'Peter': {'may': ''},
'Steven': {'april': '14/03'},
'Will': {'january': '7/01'}}
And as to your comment regarding adding month
and day
, you can add them similarly:
In [28]: for k, v in names.iteritems():
results[k] = {'month': v, 'day': dates.setdefault(k, '')}
....:
....:
In [30]: results
Out[30]:
{'George': {'day': '21/02', 'month': 'march'},
'Mary': {'day': '2/02', 'month': 'february'},
'Peter': {'day': '', 'month': 'may'},
'Steven': {'day': '14/03', 'month': 'april'},
'Will': {'day': '7/01', 'month': 'january'}}
And if you want to omit day
completely in the case where a value doesn't exist:
In [8]: results = {}
In [9]: for k, v in names.iteritems():
...: results[k] = {'month': v}
...: if dates.has_key(k):
...: results[k]['day'] = dates[k]
...:
...:
In [10]: results
Out[10]:
{'George': {'day': '21/03', 'month': 'march'},
'Mary': {'day': '2/02', 'month': 'february'},
'Peter': {'month': 'may'},
'Steven': {'day': '14/03', 'month': 'april'},
'Will': {'day': '7/01', 'month': 'january'}}
And in the odd case where you know the date but not the month, iterating through the set of the keys (as @KayZhu suggested) with a defaultdict
may be the easiest solution:
In [1]: from collections import defaultdict
In [2]: names = {'Will': 'january', 'Mary': 'february', 'George': 'march', 'Steven': 'april', 'Peter': 'may'}
In [3]: dates = {'Will': '7/01', 'George': '21/03', 'Steven': '14/03', 'Mary': '2/02', 'Marat': '27/03'}
In [4]: results = defaultdict(dict)
In [5]: for name in set(names.keys() + dates.keys()):
...: if name in names:
...: results[name]['month'] = names[name]
...: if name in dates:
...: results[name]['day'] = dates[name]
...:
...:
In [6]: for k, v in results.iteritems():
...: print k, v
...:
...:
George {'day': '21/03', 'month': 'march'}
Will {'day': '7/01', 'month': 'january'}
Marat {'day': '27/03'}
Steven {'day': '14/03', 'month': 'april'}
Peter {'month': 'may'}
Mary {'day': '2/02', 'month': 'february'}
C# Dictionary takes duplicate Keys / can't find Keys when calculated
Thanks to great help, I found out that double is really imprecise and might carry decimal places that won't show up because of internal rounding errors.
If you google for something like "issue with double error" or "double precision issue", you will find many who tried to solve it by writing custom methods to round the doubles by parsing them or the like. Many suggest to use decimal instead.
In my case, the single one thing that worked is converting the price / key double to an integer and then dividing it by the number of decimal places when needed.
Here a Wikipedia link about the why.
Related Topics
Get Button Pressed Id on Swift Via Sender
Swift: Setting an Optional Property of a Protocol
Select() from Linq in Swift 3.0
How to Scale Text to Fit Parent View with Swiftui
What's the Difference Between Aranchor and Anchorentity
Why Is Manually Setup Root View Controller Showing Black Screen
Swiftui: Can't Get the Transition of a Detailview to a Zstack in the Mainview to Work
Swift: Extending Functionality of Print() Function
Ios13 Navigation Bar Large Titles Not Covering Status Bar
Projecting the Arkit Face Tracking 3D Mesh to 2D Image Coordinates
Swiftui - Passing Data from Swiftuiview to Scenekit
What's the Difference Between Struct Based and Class Based Singletons
Xcode 7.3/Swift 2: "No Method Declared with Objective-C Selector" Warning
Making Simple Accordion Tableview in Swift
Split a String Without Removing the Delimiter in Swift
How to Get the Index of the Element in the List in Swiftui When the List Is Populated with the Array