Skip to content

Sig fig context - #1474

Open
pstaabp wants to merge 20 commits into
openwebwork:PG-2.21from
pstaabp:sig-fig-context
Open

Sig fig context#1474
pstaabp wants to merge 20 commits into
openwebwork:PG-2.21from
pstaabp:sig-fig-context

Conversation

@pstaabp

@pstaabp pstaabp commented Jul 21, 2026

Copy link
Copy Markdown
Member

This creates a context for Significant Figures and huge thanks to @dpvc for all the help and @sfiedle1 for ideas, code and other suggestions.

In short, this handles the creation of a number type that keeps track of the number of its significant figures. Although the number is stored as a floating point, the string method rounds to the appropriate number of significant figures.

Here are a few features:

  • The operations +, -, *, /, ^ are all defined with operations between SigFig numbers. See Sig fig improvements pstaabp/pg#25 for a post from @dpvc about thoughts about this.
  • There is ability to define a number with infinite number of significant figures. This would allow an operation like 1.23^3 to result in an expected number with 3 sigfigs instead of 1, since 3 only has 1 sig fig.
  • There are two flags that allow authors to specify some partial credit as well as informational messages if a student answer is either close to the real answer with correct number of sig figs OR the correct answer with an incorrect number of sigfigs. Note: I think these flags can use some better names.
  • There is a LimitedSignificantFigures context which disallows computations similar to other contexts.
  • Using the contextExtensions.pl macro, problems using both SignificantFigures and Units can be used together.

There are two test suites. significant_figures.t tests only numbers and operations between numbers. significant_figures_units.t includes some simple tests for numbers with units.

I have attached 4 sample problems.

  1. This has addition, subtraction and multiplication of 2 numbers.
  2. This has a basic number with units.
  3. This shows the two flags mentioned above.
  4. An example with the LimitedSignificantFigure context.

setsig_fig.zip

If we can get this into 2.21, that would be great. It doesn't affect anything else. If not, I'll retarget to develop.

Also, for historical purposes, there is other discussion: pstaabp/pull/25 pstaabp/pull/32, pstaabp/pull/34 and pstaabp/pull/36

@dpvc

dpvc commented Jul 22, 2026

Copy link
Copy Markdown
Member

One thing to note is that this context only handles constant computations, not formulas involving significant figures. That can be added later, but will take more work that hasn't been done yet.

Similarly, as Peter mentions, the current context only supports addition, subtraction, multiplication, division, and powers. So other functions, like trigonometric functions, logs, roots, etc., aren't yet implemented. The comments that I made that Peter links to above give one approach that could be taken for such functions.

A full significant figures context should handle these other situations, but this is certainly useful as it stands.

@pstaabp

pstaabp commented Jul 23, 2026

Copy link
Copy Markdown
Member Author

@dpvc I think the use case that @sfiedle1 had originally was only for computations, but will look into extending to Formulas and also adding additional functions.

pstaabp and others added 20 commits July 23, 2026 10:16
This includes flags for determining if a problem is to check to see if an answer has the correct # of sig figs and/or is close and give partial credit.
when using the extension with Units context and added a test for units with significant figures.
Also fixed an issue with the testing for "closeness" between student and correct sigfig answers.
Also, some improvements to language on tests.
And add in a test for partial credit.
@dpvc

dpvc commented Jul 26, 2026

Copy link
Copy Markdown
Member

[I] will look into extending to Formulas and also adding additional functions.

The externs to formulas is non-trivial, and will require overriding a number of internal functions, so not something you may be able to do without assistance. I outlined an approach for handling functions in the comments you link to above, so that is something you may be able to implement more readily. I tried it out at one point, and think it worked out pretty well.

@pstaabp

pstaabp commented Jul 27, 2026

Copy link
Copy Markdown
Member Author

@dpvc I got a note from @sfiedle1 about using flags in the extended context with units. Here's a pg file:

DOCUMENT();

loadMacros("PGstandard.pl","PGML.pl",'contextSignificantFigures.pl', 'contextUnits.pl');

Context(context::Units::extending("SignificantFigures")->withUnitsFor('mass'));

Context()->flags->set(
      tolerance                   => 0.01,
      partial_incorrect_sf        => 0.6,
      partial_sf_within_tolerance => 0.8,
      );

$a1 = Real(random(100,200,0.1), sigfigs => 4);
$b1 = Real(random(50,90,0.01), sigfigs => 4);

$a = Compute("$a1 g");
$b = Compute("$b1 g");
$c = $a+$b;

BEGIN_PGML
A lab technician has a beaker with [$a] of water.  She adds [$b] to the beaker.  Using the proper number of significant figures, what is the total amount in the beaker? 

[_]{$c}
END_PGML

ENDDOCUMENT();

This should give partial credit for numbers that are close with either correct or incorrect number of sig figs.

Doing some troubleshooting, it looks like cmp_postprocess is not called in either contextSignificantFigures.pl or contextUnits.pl and this is where the partial credit flags are checked.

@dpvc

dpvc commented Jul 27, 2026

Copy link
Copy Markdown
Member

The cmp_postprocess() method is called by the code in pg/lib/Value/AnswerChecker.pm as part of the general cmp() method handling for the MathObject that represents the correct answer. In this case, the correct answer is a NumberWithUnit object, so it is that objects cmp_postproces() method that is called. Because there is no cmp() call for the significant figures real object that is part of the NumberWithUnit object, the significant figure's cmp_postproces() method is never involved.

MathObjects that use other math objects internally don't usually use those object's cmp() methods. For example, a Vector object doesn't call the cmp() or other cmp-related functions of the entries in the vector, and a Complex number would not call the cmp functions for its real and imaginary parts. This is the standard approach with MathObjects.

Trying to combine the various partial credits for the outer object and its parts would be a complicated process. For example, the NumberWithUnit object gives partial credit for a correct number but wrong units (or units in the wrong order if exact order is required); how should that interact with partial credit for the number itself? Those are not decisions that the NumberWithUnits object can reliably make on its own, as it doesn't know what the conditions for partial credit are for the number, and when it is appropriate to do its own partial credit, or how to combine the two partial credits.

One solution would be to provide a custom checker that does what you want, and then use something like

[___]{$c->cmp(checker => &$context::SignificantFigures::unitChecker)}

or something like that. A bit ugly, but easily handled.

A solution that is easier for the problem author would be to provide a SignificantFigures-Units context that starts with context::Units::extending("SignificantFigures") and overrides the NumberWithUnit MathObject with a subclass of it that replaces the cmp_postprocess() function with one that handles the significant figures number's partial credit options as well as the units partial credit options, and combines them in the way you think they should be combined.

One complication with this is that it would depend on the Units context, so you would need that to be loaded before you could make the context::Units::extending() call; but you probably don't want to have contextSignificantFigures.pl to load contextUnits, as that would be a large overhead for those not using units. Instead, you would either make the SignificantFigures-Units context into a separate file that loads the significant figures and the units contexts and creates the combined one (the easier approach), or have the SignificantFigures-Units context be built only when the contextUnits.pl file has been loaded, in which case the problem author needs to load contestUnits.pl before contextSignificantFigures.pl (allowing you to have everything in one file).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants