Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Numbers Concept Exercise]: Rethink/Redesign #2951

Closed
BethanyG opened this issue Feb 21, 2022 · 16 comments · Fixed by #3287
Closed

[Numbers Concept Exercise]: Rethink/Redesign #2951

BethanyG opened this issue Feb 21, 2022 · 16 comments · Fixed by #3287
Labels
improve exercise 💖 x:size/large Large amount of work x:status/claimed Someone is working on this issue

Comments

@BethanyG
Copy link
Member

Per issues #2946 , #2621 , #2835, #2804, #2591, and #2490 -- this exercise has gone through a lot of improvements and also complaints.

Since multiple re-works and improvements have not succeeded, we have decided a complete re-design of the Numbers exercise is in order.

Concept docs can be retained, or revised as needed. Design documents should be updated.

Original specs for Numbers exercise are below:


Goal

The goal of this exercise is to teach the basics of theint , float , and complex numeric types (numbers) in Python.

Learning objectives

  • understand the difference between int, float and complex numbers in Python
  • understand that Python uses j to represent the square root of -1. appending j to a number defines it as imaginary. (e.g.3j is equivalent of 3(sqrt(-1)) -- IF Pythons math module allowed negative square roots...it doesn't).
  • understand that a decimal (.) preceeded or followed by a number creates a float literal
  • create an imaginary literal via appending j to an int or float (e.g. 3.4j or 5j)
  • create a float by casting an int and an int by casting a float, using the int() and float() constructors.
  • create complex numbers by casting int and float to complex using the complex() constructor.
  • create a complex number by adding a float and an imaginary literal (e.g. 3.0 + 6j)
  • understand when and how Python uses arithmetic conversions to apply arithmetic operators between these numeric types.
  • apply the arithmetic operators to each/between each of the number types (where applicable)
  • perform integer (floor) division and "regular" (float) division and see how they differ.
  • changing precision of a float, using round(<float>, <digits>)

Out of scope

  • Special values for Infinity and NaN
  • Special math functions for complex numbers contained in cmath
  • Bitwise operations on ints
  • round numbers using math.floor() and math.ceiling()
  • Issues with precision limits & sys.float_info -- but maybe we should note these in passing, or link to them in links.
  • Numpy and the numeric types defined by Numpy -- again, something for links/notes.
  • Checking strings to see if they are floats. This means any test input to this exercise should not require a student to (a) catch or raise an Exception if a non-float string is passed, or (b) check to see if the string is a float. Only pass valid float strings, i.e. "1.032".

Concepts

  • numbers
  • arithmetic operations

Prerequisites

  • basics

Resources to refer to

Hints

Hints can link to the builtin function docs mentioned above, with appropriate prompts.

Concept Description

(a variant of this can be used for the v3/languages/python/concepts/<concept>/about.md doc and this exercises introduction.md doc.)

Python has three different types of built-in numbers: integers (int), floating-point (float, and complex (complex). Fractions (fractions.Fraction) and Decimals (decimal.Decimal) are also available via import from the standard library.

Whole numbers (including hex, octals and binary numbers) without decimal places are identified as ints:

#whole number
>>> 1234
1234
>>> type(1234)
<class 'int'>

>>>  -12
-12

#hex number
>>> 0x17
23
>>> type(0x17)
<class 'int'>

#octal number
>>> 0o446
294
>>> type(0o446)
<class 'int'>

#binary number
>>> 0b1100110
102
>>> type(0b1100110)
<class 'int'>

Numbers containing a decimal point are identified as floats:

>>> 3.45
3.45
>>> type(3.45)
<class 'float'>

Appending `j` or `J` to a number creates a _imaginary number_ -- a `complex` number with a zero real part. Integers or floats can then be added to an imaginary number to create a `complex` number with both real and imaginary parts:

>>> 3j
3j
>>> type(3j)
<class 'complex'>

>>> 3.5+4j
(3.5+4j)

Arithmetic

Python fully supports arithmetic between these different number types, and will convert narrower numbers to match their less narrow counterparts when used with binary arithmetic operators (+, -, *, /, and %). ints are narrower than floats, which are considered narrower than complex. Comparisons between different number types behaves as as if the exact values of those numbers were being compared:

#the int is widened to a float here, and a float is returned
>>> 3 + 4.0
7.0

#the int is widened to a complex number, and a complex number is returned
>>> 6/(3+2j)
(2+2j)

#division always returns a float, even if integers are used
>>> 6/2
3.0

#if an int result is needed, you can use floor division to truncate the result
>>> 6//2
3

#when comparing, exact values are used
>>> 23 == 0x17
True

>>> 0b10111 \== 0x17
True

>>> 6 == (6+0j)
True

All numbers (except complex) support the same general arithmetic operations, evaluated according to operator precedence.

Precision & Representation

Integers in Python have arbitrary precision -- the amount of digits is limited only by the available memory of the host system.

Floating point numbers are usually implemented using a double in C (15 decimal places of precision), but will vary in representation based on the host system. Complex numbers have a real and an imaginary part, both of which are represented by floating point numbers.

For a more detailed discussion of the issues and limitations of floating point arithmetic, take a look at The Python Tutorial.

Implementing

Tests should be written using unittest.TestCase, and the test file named numbers_test.py.

Code in the .meta/example.py file should only use syntax & concepts introduced in this exercise or one of its prerequisites.
Please do not use comprehensions, generator expressions, or other syntax not previously covered. Please also follow PEP8 guidelines.

Help

If you have any questions while implementing the exercise, please post the questions as comments in this issue.

@BethanyG BethanyG added x:size/large Large amount of work claimed 🐾 For new exercises being written by contributors and maintainers. x:status/claimed Someone is working on this issue improve exercise 💖 labels Feb 21, 2022
@exercism exercism deleted a comment from github-actions bot Feb 21, 2022
@DjangoFett
Copy link
Contributor

I was preparing to work on this. Commenting here for the ticket to be assigned

@mohmad-null
Copy link

understand that Python uses j to represent the square root of -1. appending j to a number defines it as imaginary. (e.g.3j is equivalent of 3(sqrt(-1)) -- IF Pythons math module allowed negative square roots...it doesn't).

This seems like an oddly specific learning objective and another example of over-complex math being introduced.

In fact, the same goes for complex and imaginary numbers. I've used Python for innumerable real-world problem solving things over the past decade+ in a variety of domains and have never once used either complex or imaginary (I also have no idea what they are, so you'd have to overcome that hurdle too, likely with many other users as well).

I appreciate they may be useful for some domains but I'd posit the teaching should be things that will benefit all python users and that almost all users will need at some point.
In that vein, math.floor() and math.ceiling() would seem worthwhile, as would converting from strings and catching bad strings. All much more common things

@BethanyG
Copy link
Member Author

Hi @mohmad-null 👋🏽

As clearly stated at the top of the description (emphasis mine):

Design documents should be updated.

The specs here were provided as a reference to the person who will be re-architecting the exercise, not a commandment nor set of debate points. I'll let @DjangoFett speak to the plans he has going forward (if he wants to do that), although he shouldn't feel that he has to.

I am also going to ask you going forward to either PR a concept exercise for numbers you feel is better or stop complaining about the existing one. At this point, we understand the need to re-work this particular exercise and also look at how we deal with the different numeric types in additional exercises.

But I don't think having a debate about the utility of complex numbers (or any other numeric type) in programming is helpful. Nor do I want to have a debate about which math is "too complicated" or "unnecessary". I am interested in crafting exercises that don't excessively confuse or frustrate students and (hopefully) help then become more fluent in Python.

The author of this re-worked exercise may or may not include complex numbers in the rewrite - that is up to them. They understand the feedback and the struggles. We may or may not have other exercises that cover complex numbers in the future. This is one exercise of many that will deal with numbers and math. We are by no means done with the exercise tree.

As for the math module -- if you would like to propose a new concept exercise around that -- please do. Or a concept exercise around math that goes beyond +, -, /, //, and *. Neither are on the priority list the moment (we'd like to build out basic data structures, classes, and functions first), but we'd welcome proposals for the "next wave" of exercises to build out.

Please also feel free to propose one or more practice exercises around topics you feel we haven't gotten to yet.

@mohmad-null
Copy link

But I don't think having a debate about the utility of complex numbers (or any other numeric type) in programming is helpful. Nor do I want to have a debate about which math is "too complicated" or "unnecessary". I am interested in crafting exercises that don't excessively confuse or frustrate students and (hopefully) help then become more fluent in Python.

By definition if the math is too complex then you will be creating exercises that are going to confuse and frustrate students who do not have that math. See also my comments in this thread: exercism/problem-specifications#1902 which are highly pertinent.

I am also going to ask you going forward to either PR a concept exercise for numbers you feel is better or stop complaining about the existing one.

As noted in my other comment, I'd genuinely forgotten I'd raised the issues months previously; I wasn't being vexatious. The fact they came up again when another mentee did them 3 months later only re-enforces my point,

As clearly stated at the top of the description (emphasis mine): Design documents should be updated.

Sorry, but I don't know what that means. If you're saying "we don't want feedback at this point", then sure, I'll wait.

@DjangoFett
Copy link
Contributor

Hi @mohmad-null, I'm submitting a couple exercises as a form of a/b testing. If you want to submit your own PRs as well, I'm super into it. The way I'm envisioning tackling complex / imaginary exercises are in a separate PR still related to this issue and simplifying the current arithmetic exercises (read: currency exchange). My plan is to borrow exercises from other languages that cover the same exercise and craft them for python. Most importantly I want to submit more than one exercise covering the same thing in order to foster a conversation about which one is possibly more effective.

@BethanyG
Copy link
Member Author

BethanyG commented Mar 1, 2022

@mohmad-null

Sorry, but I don't know what that means. If you're saying "we don't want feedback at this point", then sure, I'll wait.

We don't want more of the same feedback on the existing exercise at this point, since @DjangoFett is re-designing it, and has also taken on thinking through multiple exercises with regards to numbers in Python. Hence the comment about updating design docs -- he may very well end up with design docs that split the topic into multiple concepts and topics.

So do please either participate by PR-ing an additional exercise/exercises as he's welcomed above, or give him and others time to re-work things before launching a long discussion on how math or numbers should or should not be taught. Thanks. 🙂

@github-actions

This comment was marked as outdated.

@DjangoFett
Copy link
Contributor

Not Abandoned! Just slower than I'd like

@BethanyG
Copy link
Member Author

For shame, github bot! For shame.

@exercism exercism deleted a comment from github-actions bot Apr 14, 2022
@ErikSchierboom ErikSchierboom added x:size/large Large amount of work and removed x:size/large Large amount of work labels Apr 26, 2022
@BethanyG
Copy link
Member Author

@DjangoFett - its been a bit and I know you have a LOT going on, so I am going to un-assign you from this task right now. I have another contributor who may take it on. However, I am more than happy to also have you work on it or collaborate - just let me know! And many thanks for all your efforts thus far. 😄 💙 🙏🏽

@BethanyG BethanyG removed the claimed 🐾 For new exercises being written by contributors and maintainers. label May 14, 2022
@BethanyG BethanyG changed the title [Numbers] Redesign Numbers Concept Exercise [Numbers Concept Exercise]: Rethink/Redesign May 21, 2022
@BethanyG
Copy link
Member Author

Bad Bot! Stop marking this abandoned.

@BethanyG
Copy link
Member Author

BethanyG commented Sep 9, 2022

Nope.

@BethanyG
Copy link
Member Author

Stop it, stale bot!

@MondoBurrito
Copy link

MondoBurrito commented Oct 27, 2022

Hi everyone. I believe I am the perfect person to chime in here... specifically about the Currency Conversion exercise. I am a noobie who, like millions of other noobies, are struggling to learn to code.
This particular exercise was just too overly complex and frustrating... especially when one is trying so hard to learn the basics of coding.

On the surface, it seems simple. Division, multiplication... a bit of addition and subtraction. But building the formulas was way more complicated than it should be due to the sheer AMOUNT of variables and functions required. I was at the point where I had no idea what to do with all these variables... or even what variables to create to get the job done.

It. was. just. too. much. Too much for one exercise.

I'm sure an experienced programmer would have this nailed in 5 minutes.... but I spent multiple days (about 5-6 hours total) working on this... only to end in failure and despair. I just caved in and looked at a solution. Totally defeated.

This is not an issue with Python itself. Nor is it an issue with syntax. This was a problem with math.

I know that coding is hard. Trust me, I get it. I know a person needs grit. But beginners need momentum and a sense of making progress. There is nothing more frustrating than running in circles and banging your head against the wall for days on end.

Anyway, I know you guys are likely well aware of this, but I think that most people who create these coding challenges suffer from "The Curse of Knowledge." When you become really good at programming, you forget what it is like to be a beginner.

Anyway, I was able to sharpen my problem solving skills with this one... so I will give it that. I just could not finish it on my own because it was too hard.

Thanks for listening.

@github-actions
Copy link
Contributor

This issue has been automatically marked as abandoned 🏚 because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@BethanyG
Copy link
Member Author

No, bot.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
improve exercise 💖 x:size/large Large amount of work x:status/claimed Someone is working on this issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants