From 72ec10a3e612de626b030367817a5deed7683218 Mon Sep 17 00:00:00 2001 From: Karenzz Date: Thu, 30 Mar 2023 23:20:18 +0200 Subject: [PATCH] Update page 'Day 1 Homework - Karen' --- Day 1 Homework - Karen.md | 151 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 151 insertions(+) create mode 100644 Day 1 Homework - Karen.md diff --git a/Day 1 Homework - Karen.md b/Day 1 Homework - Karen.md new file mode 100644 index 0000000..5e5d2f5 --- /dev/null +++ b/Day 1 Homework - Karen.md @@ -0,0 +1,151 @@ +**1. What is the name of the international standard for floating-point representation?** +IEEE754 + +**2. How many bits are the floating point numbers defined by that standard allowed to be?** +The IEEE754 standard defines several different floating-point formats and the most common ones are the single-precision and the double-precision. +* Single-precison defines 32 bits used to represent each number, while double-precison defines 64 bits. +* The standard also has other formats, such as quadruple-precision for 128 bits. + +**3. Does your computer support all those formats? Can you think of an easy way to check with only one line of Python?** +I can easily use `numpy.finfo` to return information about the floating-point data type used by my system, and it shows that my computer uses 64 bits by default and can also use float16 and float32. However, a quadruple-precision format is not supported by my system as it returns a warning. + +![Floating-point formats](https://github.com/Karenzky/PythonBootcamp/blob/d4642e18971e820c07c72839abae6fc69f374037/float%20formats.png) + + +**4. Why doesn't this code give the same answers to the two multiplications?** +```ruby +import pandas as pd +import numpy as np + +# Generate two random 64-bit integers +num1 = np.random.randint(0, 2**63 - 1) +num2 = np.random.randint(0, 2**63 - 1) + +# Multiply them together using the normal Python multiplication operator +print(f"num1 * num2 = {num1 * num2}") + +# Create a Pandas DataFrame with the generated numbers +data = {'Number1': [num1], 'Number2': [num2]} +df = pd.DataFrame(data) + +# Multiply the numbers together using the Pandas multiplication operator +df['Product'] = df['Number1'] * df['Number2'] + +print(df) +``` +It's because that the result of the multiplication operation on two integers is also an integer while the multiplication on two columns in pandas dataframe returns a new column of the same type as the input columns. To be more specific, the multiplication of two 64-bit integers (num1 & num2 here in this first example) can result in a number that requires more than 64 bits to represent, and the result reports a value error that high is out of bounds for int64 when I run this script; however, an integer column here using the pandas multiplication operator will have a maximum size of 64 bits and will cause a loss of precision. + + +**5. You can use `sys.getsizeof` to see how large a Python object is. Does the size of a Python floating-point number change as it gets larger? Why or why not?** +The size of a Python floating-point number doesn't change, because the floating-point numbers are stored in a fixed number of bytes regardless of their specific value. In python, a floact object always takes up 8 bytes of memory and it will not change no matter for how large a Python object is. +![Floating-point change check](https://github.com/Karenzky/PythonBootcamp/blob/e70b05bcf39dc7efcf93c90322912ef9aff2a257/sys.png) + +**6. We already know that the precision of floating-point numbers decreases as their magnitude increases. Using Pandas, create a dataframe representing a large amount of US Dollars. What is the smallest number of dollars where adding one cent begins to yield wrong results?** +Firstly, a large amount of US Dollars can be created by multiplying the numbers 1 through 1000000 by 10 billion that returns results ranging from 10 billion to 10 trillion dollars (I am sure it should be a large amount lol), and then Dollars column can be created using Pandas to store those dollar values. +```ruby +import pandas as pd + +dollars = [n * 10**10 for n in range(1, 1000000)] +df = pd.DataFrame({'Dollars': dollars}) +``` +As for the next step to find the smallest number of dollars where adding one cent begins to yield wrong results, we can iterate over the DataFrame and add one cent to each dollar amount, and then compare the result to the original amount. The smallest value will be found once the new amount does not equal to the original amount plus one cent. +```ruby +for index, row in df.iterrows(): + original_dollars = row['Dollars'] + new_dollars = original_dollars + 0.01 + if new_dollars != original_dollars + 0.01: + print(f"Smallest amount: {original_dollars:.2f}") + break +``` + +**7. Name three practical differences between Python strings and bytes. Using `sys.getsizeof`, see how the sizes may be different. Do emoji change this answer?** +* Representation: strings are represented using quotes, while bytes use a prefix of `b` followed by quotes. +* Encoding: strings can have a wide range of characters from various writing systems, while bytes use to store non-textual data or text encoded only in a specific character encoding such as UTF-8. +* Mutability: stings can not be modified so that a new string need to be created every time a change is needed. On the other hand, bytes are mutable and can be modified in place. + +Emojis do change the result, supposing it is occurred because the encoding used by emoji. In UTF-8 encoding, it are represented using multiple bytes, so it may cause larger size. + +```ruby +import sys +x = 'pizza' +y = b'pizza' +z = 'πŸ•' + +print(sys.getsizeof(x)) +print(sys.getsizeof(y)) +print(sys.getsizeof(z)) + +#The results are shown as +#>>pandas) PS C:\Users\Karen\pandas> & C:/Users/Karen/GTSP_DA_Intern/pandas/Scripts/python.exe c:/Users/Karen/pandas/hm.py +#54 +#38 +#80 +``` +![Emoji](https://github.com/Karenzky/PythonBootcamp/blob/cb586168d33823d79c54380925eaae2901c2c4c2/emoji.png) + +**8. Given this sample CSV file (tomato_sales.csv):** +``` +Store,Region,Tomato_Sales +Store1,East,300 +Store2,West,450 +Store3,North,500 +Store4,South,350 +Store5,East,400 +``` +**and this Python file to do a simple accounting function:** +``` +def read_tomato_sales(file_name): + data = pd.read_csv(file_name) + total_sales = data["Tomato_Sales"].sum() # This will raise an error + print(f"Total tomato sales: {total_sales}") + +read_tomato_sales("tomato_sales_error.csv") +``` +**describe a hypothetical situation where modifying the CSV file to create a type confusion error could cause nuclear war due to AIs taking over the food supply chain.** +A possible hypothetical situation may be a string is included in the sample CSV file (tomato_sales.csv). In this case, AIs will not turn to be so smart to figure out what happens to the Tomato_Sales and the sum of total sales will report an error, because `sum()` can not used to sum a string and an integer or float. + +**9. Prevent that nuclear war by modifying `read_tomato_sales` to perform better data validation.** +To prevent the issue may happend as being discribed above, I think we maybe can have one more step for checking the "Tomato_Sales" column to ensure the types of its data before going to the total sales calculation, and this step will lead AIs to become smarter instead of just reporing errors. +```ruby +def read_tomato_sales(file_name): + data = pd.read_csv(file_name) + if not pd.api.types.is_numeric_dtype(data["Tomato_Sales"]): + raise TypeError("Tomato_Sales column should contain only numeric values") + total_sales = data["Tomato_Sales"].sum() + print(f"Total tomato sales: {total_sales}") + +read_tomato_sales("tomato_sales_error.csv") +``` + +**10. Given today's conversation about character encodings, describe why you would want to use bytes instead of strings when processing data containing multiple human languages at the same time. Write a small Python function to demonstrate this.** +As being discussed above regarding the three main differences between python strings and bytes, the initial reason I will use bytes instead of strings for process data containing multiple human languages is that bytes allow more flexibility and mutability of handling multilingual texts. Besides numerical values, bytes also can encode text data in different character sets without any potential loss of information, such as UTF-8 and UTF-16. For example, we can defer an encoding and decoding process of text data to see how it can be used in different language situations. +``` +def encode_text(text, encoding='utf-8'): + encoded_text = text.encode(encoding) + return encoded_text + +def decode_text(encoded_text, encoding='utf-8'): + decoded_text = encoded_text.decode(encoding) + return decoded_text +``` +Well, I do say it is amazing as the whole encoding process is seamless and suppose my computer will help me to do it (thanks to it). To assume we work in a multiple languages environment and we review yesterday's conversation about Nemawashi, the encoding process allows us to translate different languages into binary data using UTF-8 and people in different language can easily decoding it to be the textual data more efficiently without any loss of information (such loss of information may be caused by the different system used by different people, I usually meet this kind of issues when using emojis and enter any language items that others' computer may not be applicable to read it). +```ruby +def encode_text(text, encoding='utf-8'): + encoded_text = text.encode(encoding) + return encoded_text + +def decode_text(encoded_text, encoding='utf-8'): + decoded_text = encoded_text.decode(encoding) + return decoded_text + +text = "Nemawashi, δΊ‹ε…ˆη–ι€šοΌŒγ­γΎγ‚γ—" +encoded_text = encode_text(text, 'utf-16') +print(encoded_text) + +decoded_text = decode_text(encoded_text, 'utf-16') +print(decoded_text) + +#The results are shown as +#b'\xff\xfeN\x00e\x00m\x00a\x00w\x00a\x00s\x00h\x00i\x00,\x00 \x00\x8bNHQ\x8fu\x1a\x90\x0c\xffm0~0\x8f0W0' +Nemawashi, δΊ‹ε…ˆη–ι€šοΌŒγ­γΎγ‚γ— +```