The purpose of this task is to use scientific notation in the context of choosing units to report quantities. The teacher may wish to have students reflect on how the choice of units in each part either helps or hinders our ability to grasp the quantity under consideration. There is always a wide choice of units available and we should try to choose units which are most appropriate for communicating the size of an object without further calculations or conversions. Scientific notation is particularly useful when the quantities being described are very small or very large (though a good choice of units can often remove the need for these small or large quantities).
In part (a), students have an intuition, based on experience, for how much 1 gigabyte of storage is and so expressing the computer memory as 128 gigabytes is helpful. When we use scientific notation and write this in terms of bytes or kilobytes, the number is very large and does not carry much useful information except for an expert. For the situations presented in (b) and (c), neither seconds nor teaspoons is an appropriate unit of measure to give a good intuition for the quantities in question. There are many reasonable choices. For (b), hours is probably the best choice but even minutes or days would be better than seconds. For part (c), students will likely need a conversion factor. In metric units, there are about 4.9 ml in a teaspoon. In metric units, the best choice for giving an intuition for the size of the swimming pool is probably cubic meters. In standard units, gallons are too small: cubic feet or yards would be appropriate but the conversion will be difficult.
In extreme situations like the helium atom example in part (d), any choice of units will have both advantages and disadvantages. Picometers are a natural choice for measuring an atom in the sense that the number of picometers needed is a reasonable size number. On the other hand, we have little physical experience that allows us to grasp what a picometer is. If we choose the more comfortable unit of meters, then we can see that it takes many, many helium atom diameters to make a meter: unfortunately, it is difficult to imagine billions of atoms and so this also has a downside. When dealing with very large or very small quantities, this dilemma always exists and it is only by gaining familiarity with the given context that the units and quantities become more familiar and comfortable.
The floppy disk has 80 kilobytes of storage and there are 1000 bytes in a kilobyte so this is 80,000 or $8 \times 10^4$ bytes of storage. There are $1 \times 10^9$ bytes in a gigabyte so the floppy disk storage is $$\frac8 \times 10^4 \text bytes1 \times 10^9 \text bytes per gigabyte.$$ This is $8 \times 10^4-9 = 8 \times 10^-5$ gigabytes. There are 0.00008 gigabytes of storage on a floppy disk.
Solidity is a statically typed language, which means that the type of eachvariable (state and local) needs to be specified.Solidity provides several elementary types which can be combined to form complex types.
The result of a shift operation has the type of the left operand, truncating the result to match the type.The right operand must be of unsigned type, trying to shift by a signed type will produce a compilation error.
Before version 0.5.0 a right shift x >> y for negative x was equivalent tothe mathematical expression x / 2**y rounded towards zero,i.e., right shifts used rounding up (towards zero) instead of rounding down (towards negative infinity).
The expression type(int).min / (-1) is the only case where division causes an overflow.In checked arithmetic mode, this will cause a failing assertion, while in wrappingmode, the value will be type(int).min.
Exponentiation is only available for unsigned types in the exponent. The resulting typeof an exponentiation is always equal to the type of the base. Please take care that it islarge enough to hold the result and prepare for potential assertion failures or wrapping behavior.
In checked mode, exponentiation only uses the comparatively cheap exp opcode for small bases.For the cases of x**3, the expression x*x*x might be cheaper.In any case, gas cost tests and the use of the optimizer are advisable.
fixed / ufixed: Signed and unsigned fixed point number of various sizes. Keywords ufixedMxN and fixedMxN, where M represents the number of bits taken bythe type and N represents how many decimal points are available. M must be divisible by 8 and goes from 8 to 256 bits. N must be between 0 and 80, inclusive.ufixed and fixed are aliases for ufixed128x18 and fixed128x18, respectively.
The main difference between floating point (float and double in many languages, more precisely IEEE 754 numbers) and fixed point numbers isthat the number of bits used for the integer and the fractional part (the part after the decimal dot) is flexible in the former, while it is strictlydefined in the latter. Generally, in floating point almost the entire space is used to represent the number, while only a small number of bits definewhere the decimal point is.
The idea behind this distinction is that address payable is an address you can send Ether to,while you are not supposed to send Ether to a plain address, for example because it might be a smart contractthat was not built to accept Ether.
Only expressions of type address and contract-type can be converted to the type addresspayable via the explicit conversion payable(...). For contract-type, this conversion is onlyallowed if the contract can receive Ether, i.e., the contract either has a receive or a payable fallback function. Note that payable(0) is valid and isan exception to this rule.
If you need a variable of type address and plan to send Ether to it, thendeclare its type as address payable to make this requirement visible. Also,try to make this distinction or conversion as early as possible.
The distinction between address and address payable was introduced with version 0.5.0.Also starting from that version, contracts are not implicitly convertible to the address type, but can still be explicitly converted toaddress or to address payable, if they have a receive or payable fallback function.
If x is a contract address, its code (more specifically: its Receive Ether Function, if present, or otherwise its Fallback Function, if present) will be executed together with the transfer call (this is a feature of the EVM and cannot be prevented). If that execution runs out of gas or fails in any way, the Ether transfer will be reverted and the current contract will stop with an exception.
There are some dangers in using send: The transfer fails if the call stack depth is at 1024(this can always be forced by the caller) and it also fails if the recipient runs out of gas. So in orderto make safe Ether transfers, always check the return value of send, use transfer or even better:use a pattern where the recipient withdraws the Ether.
In order to interface with contracts that do not adhere to the ABI,or to get more direct control over the encoding,the functions call, delegatecall and staticcall are provided.They all take a single bytes memory parameter andreturn the success condition (as a bool) and the returned data(bytes memory).The functions abi.encode, abi.encodePacked, abi.encodeWithSelectorand abi.encodeWithSignature can be used to encode structured data.
All these functions are low-level functions and should be used with care.Specifically, any unknown contract might be malicious and if you call it, youhand over control to that contract which could in turn call back intoyour contract, so be prepared for changes to your state variableswhen the call returns. The regular way to interact with other contractsis to call a function on a contract object (x.f()).
It is best to avoid relying on hardcoded gas values in your smart contract code,regardless of whether state is read from or written to, as this can have many pitfalls.Also, access to gas might change in the future.
You can query the deployed code for any smart contract. Use .code to get the EVM bytecode as abytes memory, which might be empty. Use .codehash to get the Keccak-256 hash of that code(as a bytes32). Note that addr.codehash is cheaper than using keccak256(addr.code).
Explicit conversion to and from the address payable type is only possibleif the contract type has a receive or payable fallback function. The conversion is stillperformed using address(x). If the contract type does not have a receive or payablefallback function, the conversion to address payable can be done usingpayable(address(x)).You can find more information in the section aboutthe address type.
The shifting operator works with unsigned integer type as right operand (butreturns the type of the left operand), which denotes the number of bits to shift by.Shifting by a signed type will produce a compilation error.
Hexadecimal literals that pass the address checksum test, for example0xdCad3a6d3569DF655070DEd06cb7A1b2Ccd1D3AF are of address type.Hexadecimal literals that are between 39 and 41 digitslong and do not pass the checksum test producean error. You can prepend (for integer types) or append (for bytesNN types) zeros to remove the error.
Integer literals are formed from a sequence of digits in the range 0-9.They are interpreted as decimals. For example, 69 means sixty nine.Octal literals do not exist in Solidity and leading zeros are invalid.
Underscores can be used to separate the digits of a numeric literal to aid readability.For example, decimal 123_000, hexadecimal 0x2eff_abde, scientific decimal notation 1_2e345_678 are all valid.Underscores are only allowed between two digits and only one consecutive underscore is allowed.There is no additional semantic meaning added to a number literal containing underscores,the underscores are ignored.
Number literal expressions retain arbitrary precision until they are converted to a non-literal type (i.e. byusing them together with anything other than a number literal expression (like boolean literals) or by explicit conversion).This means that computations do not overflow and divisions do not truncatein number literal expressions.
c80f0f1006