[{"data":1,"prerenderedAt":2814},["ShallowReactive",2],{"doc:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python":3,"surround:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python":2780,"ancestors:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python":2789,"children:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python":2794,"related:\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python":2795},{"id":4,"title":5,"body":6,"dateModified":2748,"datePublished":2748,"description":2749,"extension":2750,"faq":2751,"keyword":2760,"kind":2761,"meta":2762,"navigation":140,"path":2770,"seo":2771,"slug":2773,"stem":2774,"topics":2775,"type":2778,"__hash__":2779},"docs\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python\u002Findex.md","ROUND, ROUNDUP, MROUND and CEILING Equivalents in Python",{"type":7,"value":8,"toc":2736},"minimark",[9,64,69,97,108,112,320,331,525,529,535,959,1005,1009,1019,1343,1376,1467,1471,2374,2386,2539,2543,2568,2572,2625,2629,2671,2675,2681,2687,2693,2699,2703,2732],[10,11,12,13,17,18,21,22,25,26,30,31,33,34,37,38,40,41,40,44,40,47,40,50,53,54,57,58,63],"p",{},"Rounding looks like the one Excel function that needs no translation — Python has ",[14,15,16],"code",{},"round()"," and pandas has ",[14,19,20],{},".round()",". Then a report rebuilt in Python disagrees with the spreadsheet by a penny here and there, and the reason is that the three do not round the same way. Excel's ",[14,23,24],{},"ROUND"," rounds halves ",[27,28,29],"em",{},"away from zero",": 2.5 becomes 3 and −2.5 becomes −3. Python's ",[14,32,16],{}," and pandas round halves ",[27,35,36],{},"to even",": 2.5 becomes 2 and 3.5 becomes 4. On top of that, many decimal fractions cannot be stored exactly in binary, so 2.675 is really 2.67499999…, which Python rounds down to 2.67 while Excel shows 2.68. For invoices, VAT and anything reconciled against a spreadsheet, those pennies matter. This page writes Python and pandas equivalents of ",[14,39,24],{},", ",[14,42,43],{},"ROUNDUP",[14,45,46],{},"ROUNDDOWN",[14,48,49],{},"MROUND",[14,51,52],{},"CEILING"," and ",[14,55,56],{},"FLOOR"," that match Excel, explains each difference, and checks every function against the same formulas recalculated in a workbook. It belongs to ",[59,60,62],"a",{"href":61},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002F","Excel Formula Equivalents in pandas",".",[65,66,68],"h2",{"id":67},"prerequisites","Prerequisites",[70,71,76],"pre",{"className":72,"code":73,"language":74,"meta":75,"style":75},"language-bash shiki shiki-themes github-light github-dark-high-contrast","pip install pandas openpyxl\n","bash","",[14,77,78],{"__ignoreMap":75},[79,80,83,87,91,94],"span",{"class":81,"line":82},"line",1,[79,84,86],{"class":85},"sMTad","pip",[79,88,90],{"class":89},"srMev"," install",[79,92,93],{"class":89}," pandas",[79,95,96],{"class":89}," openpyxl\n",[10,98,99,100,103,104,107],{},"LibreOffice (",[14,101,102],{},"soffice",") recalculates the comparison workbook in Step 4; its rounding functions follow Excel's definitions. Everything else uses the standard library's ",[14,105,106],{},"decimal"," module.",[65,109,111],{"id":110},"step-1-see-the-three-behaviours-disagree","Step 1 — See the three behaviours disagree",[70,113,117],{"className":114,"code":115,"language":116,"meta":75,"style":75},"language-python shiki shiki-themes github-light github-dark-high-contrast","import pandas as pd\n\nvalues = [0.5, 1.5, 2.5, -2.5, 2.675, 1.005, 0.125]\nprint(\"Python round:\", [round(v) for v in values[:4]], [round(v, 2) for v in values[4:]])\nprint(\"pandas round:\", pd.Series(values[:4]).round().tolist(), pd.Series(values[4:]).round(2).tolist())\nprint(\"repr of 2.675:\", f\"{2.675:.20f}\")\n","python",[14,118,119,135,142,193,257,285],{"__ignoreMap":75},[79,120,121,125,129,132],{"class":81,"line":82},[79,122,124],{"class":123},"s-kum","import",[79,126,128],{"class":127},"skGVy"," pandas ",[79,130,131],{"class":123},"as",[79,133,134],{"class":127}," pd\n",[79,136,138],{"class":81,"line":137},2,[79,139,141],{"emptyLinePlaceholder":140},true,"\n",[79,143,145,148,151,154,158,160,163,165,168,170,173,175,177,180,182,185,187,190],{"class":81,"line":144},3,[79,146,147],{"class":127},"values ",[79,149,150],{"class":123},"=",[79,152,153],{"class":127}," [",[79,155,157],{"class":156},"sP0c6","0.5",[79,159,40],{"class":127},[79,161,162],{"class":156},"1.5",[79,164,40],{"class":127},[79,166,167],{"class":156},"2.5",[79,169,40],{"class":127},[79,171,172],{"class":123},"-",[79,174,167],{"class":156},[79,176,40],{"class":127},[79,178,179],{"class":156},"2.675",[79,181,40],{"class":127},[79,183,184],{"class":156},"1.005",[79,186,40],{"class":127},[79,188,189],{"class":156},"0.125",[79,191,192],{"class":127},"]\n",[79,194,196,199,202,205,208,211,214,217,220,223,226,229,232,234,237,240,243,245,247,249,252,254],{"class":81,"line":195},4,[79,197,198],{"class":156},"print",[79,200,201],{"class":127},"(",[79,203,204],{"class":89},"\"Python round:\"",[79,206,207],{"class":127},", [",[79,209,210],{"class":156},"round",[79,212,213],{"class":127},"(v) ",[79,215,216],{"class":123},"for",[79,218,219],{"class":127}," v ",[79,221,222],{"class":123},"in",[79,224,225],{"class":127}," values[:",[79,227,228],{"class":156},"4",[79,230,231],{"class":127},"]], [",[79,233,210],{"class":156},[79,235,236],{"class":127},"(v, ",[79,238,239],{"class":156},"2",[79,241,242],{"class":127},") ",[79,244,216],{"class":123},[79,246,219],{"class":127},[79,248,222],{"class":123},[79,250,251],{"class":127}," values[",[79,253,228],{"class":156},[79,255,256],{"class":127},":]])\n",[79,258,260,262,264,267,270,272,275,277,280,282],{"class":81,"line":259},5,[79,261,198],{"class":156},[79,263,201],{"class":127},[79,265,266],{"class":89},"\"pandas round:\"",[79,268,269],{"class":127},", pd.Series(values[:",[79,271,228],{"class":156},[79,273,274],{"class":127},"]).round().tolist(), pd.Series(values[",[79,276,228],{"class":156},[79,278,279],{"class":127},":]).round(",[79,281,239],{"class":156},[79,283,284],{"class":127},").tolist())\n",[79,286,288,290,292,295,297,300,303,307,309,312,315,317],{"class":81,"line":287},6,[79,289,198],{"class":156},[79,291,201],{"class":127},[79,293,294],{"class":89},"\"repr of 2.675:\"",[79,296,40],{"class":127},[79,298,299],{"class":123},"f",[79,301,302],{"class":89},"\"",[79,304,306],{"class":305},"sSjpA","{",[79,308,179],{"class":156},[79,310,311],{"class":123},":.20f",[79,313,314],{"class":305},"}",[79,316,302],{"class":89},[79,318,319],{"class":127},")\n",[10,321,322,323,326,327,330],{},"Python and pandas both turn 0.5 into 0, 1.5 into 2 and 2.5 into 2 — ",[27,324,325],{},"banker's rounding",", which avoids a systematic upward bias when many halves are rounded, and is the IEEE 754 default. Excel gives 1, 2 and 3. The second problem is visible in the last line: the float closest to 2.675 is slightly below it, so Python's ",[14,328,329],{},"round(2.675, 2)"," gives 2.67. pandas happens to give 2.68 for that value, because it scales by 100 before rounding and the scaled float lands on the other side — but it still gives 1.0 for 1.005 and 0.12 for 0.125, where Excel shows 1.01 and 0.13. Excel works on the value as displayed, to 15 significant digits, and rounds halves away from zero; a correct equivalent has to do both, and cannot rely on whichever way a particular float happens to fall.",[332,333,341,342,341,346,341,350,341,357,341,365,341,372,341,379,341,382,341,386,341,389,341,393,341,398,341,403,341,405,341,409,341,411,341,413,341,415,341,418,341,421,341,423,341,425,341,428,341,430,341,432,341,434,341,437,341,440,341,444,341,446,341,450,341,452,341,454,341,456,341,459,341,462,341,466,341,468,341,472,341,474,341,477,341,479,341,481,341,484,341,488,341,490,341,494,341,496,341,498,341,500,341,503,341,506,341,510,341,512,341,516,341,518,341,520,341,522],"svg",{"viewBox":334,"role":335,"ariaLabelledBy":336,"xmlns":339,"style":340},"4 0 752 276","img",[337,338],"rd-modes-t","rd-modes-d","http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg","width:100%;max-width:752px;height:auto;display:block;margin:1.5rem auto;font-family:Inter,ui-sans-serif,system-ui,sans-serif","\n  ",[343,344,345],"title",{"id":337},"How each tool rounds the same values",[347,348,349],"desc",{"id":338},"Python's round and pandas round halves to the even neighbour, so 2.5 becomes 2, where Excel's ROUND gives 3. For values that cannot be stored exactly, results depend on the tool, for example 2.675 rounds to 2.67 in Python and 2.68 in pandas and Excel, while 1.005 and 0.125 round down in both Python and pandas but up in Excel.",[351,352],"rect",{"x":228,"y":353,"width":354,"height":355,"fill":356},"0","752","276","#ffffff",[351,358],{"x":359,"y":360,"width":361,"height":362,"rx":353,"fill":356,"stroke":363,"style":364},"20.0","16.0","112.0","40.0","var(--line,#cdd5e6)","stroke-width:1px",[351,366],{"x":367,"y":360,"width":368,"height":362,"rx":353,"fill":369,"stroke":370,"style":371},"132.0","202.7","#f0f4ff","var(--brand,#5b5cf0)","stroke-width:1.2px",[373,374,378],"text",{"x":375,"y":376,"style":377},"233.3","41.0","font-size:13px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Python round",[351,380],{"x":381,"y":360,"width":368,"height":362,"rx":353,"fill":369,"stroke":370,"style":371},"334.6",[373,383,385],{"x":384,"y":376,"style":377},"436.0","pandas round",[351,387],{"x":388,"y":360,"width":368,"height":362,"rx":353,"fill":369,"stroke":370,"style":371},"537.3",[373,390,392],{"x":391,"y":376,"style":377},"638.7","Excel ROUND",[351,394],{"x":359,"y":395,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"56.0","34.0","#e7ebef",[373,399,157],{"x":400,"y":401,"style":402},"32.0","78.0","font-size:12.5px;font-weight:700;fill:var(--text,#172033);text-anchor:start",[351,404],{"x":367,"y":395,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,406,353],{"x":375,"y":407,"style":408},"77.0","font-size:11.5px;font-weight:400;fill:var(--text,#172033);text-anchor:middle",[351,410],{"x":381,"y":395,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,412,353],{"x":384,"y":407,"style":408},[351,414],{"x":388,"y":395,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,416,417],{"x":391,"y":407,"style":408},"1",[351,419],{"x":359,"y":420,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"90.0",[373,422,167],{"x":400,"y":361,"style":402},[351,424],{"x":367,"y":420,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,426,239],{"x":375,"y":427,"style":408},"111.0",[351,429],{"x":381,"y":420,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,431,239],{"x":384,"y":427,"style":408},[351,433],{"x":388,"y":420,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,435,436],{"x":391,"y":427,"style":408},"3",[351,438],{"x":359,"y":439,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"124.0",[373,441,443],{"x":400,"y":442,"style":402},"146.0","-2.5",[351,445],{"x":367,"y":439,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,447,449],{"x":375,"y":448,"style":408},"145.0","-2",[351,451],{"x":381,"y":439,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,453,449],{"x":384,"y":448,"style":408},[351,455],{"x":388,"y":439,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,457,458],{"x":391,"y":448,"style":408},"-3",[351,460],{"x":359,"y":461,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"158.0",[373,463,465],{"x":400,"y":464,"style":402},"180.0","2.675 to 2 dp",[351,467],{"x":367,"y":461,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,469,471],{"x":375,"y":470,"style":408},"179.0","2.67",[351,473],{"x":381,"y":461,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,475,476],{"x":384,"y":470,"style":408},"2.68",[351,478],{"x":388,"y":461,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,480,476],{"x":391,"y":470,"style":408},[351,482],{"x":359,"y":483,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"192.0",[373,485,487],{"x":400,"y":486,"style":402},"214.0","1.005 to 2 dp",[351,489],{"x":367,"y":483,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,491,493],{"x":375,"y":492,"style":408},"213.0","1.0",[351,495],{"x":381,"y":483,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,497,493],{"x":384,"y":492,"style":408},[351,499],{"x":388,"y":483,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,501,502],{"x":391,"y":492,"style":408},"1.01",[351,504],{"x":359,"y":505,"width":361,"height":396,"rx":353,"fill":397,"stroke":363,"style":364},"226.0",[373,507,509],{"x":400,"y":508,"style":402},"248.0","0.125 to 2 dp",[351,511],{"x":367,"y":505,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,513,515],{"x":375,"y":514,"style":408},"247.0","0.12",[351,517],{"x":381,"y":505,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,519,515],{"x":384,"y":514,"style":408},[351,521],{"x":388,"y":505,"width":368,"height":396,"rx":353,"fill":356,"stroke":363,"style":364},[373,523,524],{"x":391,"y":514,"style":408},"0.13",[65,526,528],{"id":527},"step-2-excel-compatible-round-roundup-and-rounddown","Step 2 — Excel-compatible ROUND, ROUNDUP and ROUNDDOWN",[10,530,531,532,534],{},"The ",[14,533,106],{}," module rounds exactly, with a choice of rule. Converting the float through its 15-significant-digit representation first removes the binary artefact, the same way Excel does:",[70,536,538],{"className":114,"code":537,"language":116,"meta":75,"style":75},"from decimal import Decimal, ROUND_HALF_UP, ROUND_UP, ROUND_DOWN\n\ndef _dec(x):\n    return Decimal(f\"{x:.15g}\")                       # 2.675 -> Decimal('2.675'), as Excel sees it\n\ndef _quantum(digits):\n    return Decimal(1).scaleb(-digits)                 # digits=2 -> 0.01, digits=-2 -> 1E+2\n\ndef excel_round(x, digits=0, rule=ROUND_HALF_UP):\n    q = _quantum(digits)\n    d = _dec(x)\n    if digits \u003C 0:                                     # round to tens, hundreds, …\n        return float((d \u002F q).quantize(Decimal(1), rounding=rule) * q)\n    return float(d.quantize(q, rounding=rule))\n\ndef excel_roundup(x, digits=0):\n    return excel_round(x, digits, ROUND_UP)            # away from zero\n\ndef excel_rounddown(x, digits=0):\n    return excel_round(x, digits, ROUND_DOWN)          # towards zero, i.e. truncate\n\nprint([excel_round(v) for v in (0.5, 1.5, 2.5, -2.5)], excel_round(2.675, 2), excel_round(1.005, 2), excel_round(1234.5, -2))\nprint(excel_roundup(3.141, 2), excel_roundup(-3.141, 2), excel_rounddown(-3.149, 2))\n",[14,539,540,566,570,582,613,617,627,647,652,677,688,699,720,758,775,780,796,812,817,833,849,854,919],{"__ignoreMap":75},[79,541,542,545,548,550,553,556,558,561,563],{"class":81,"line":82},[79,543,544],{"class":123},"from",[79,546,547],{"class":127}," decimal ",[79,549,124],{"class":123},[79,551,552],{"class":127}," Decimal, ",[79,554,555],{"class":156},"ROUND_HALF_UP",[79,557,40],{"class":127},[79,559,560],{"class":156},"ROUND_UP",[79,562,40],{"class":127},[79,564,565],{"class":156},"ROUND_DOWN\n",[79,567,568],{"class":81,"line":137},[79,569,141],{"emptyLinePlaceholder":140},[79,571,572,575,579],{"class":81,"line":144},[79,573,574],{"class":123},"def",[79,576,578],{"class":577},"s_Opv"," _dec",[79,580,581],{"class":127},"(x):\n",[79,583,584,587,590,592,594,596,599,602,604,606,609],{"class":81,"line":195},[79,585,586],{"class":123},"    return",[79,588,589],{"class":127}," Decimal(",[79,591,299],{"class":123},[79,593,302],{"class":89},[79,595,306],{"class":305},[79,597,598],{"class":127},"x",[79,600,601],{"class":123},":.15g",[79,603,314],{"class":305},[79,605,302],{"class":89},[79,607,608],{"class":127},")                       ",[79,610,612],{"class":611},"s-wDw","# 2.675 -> Decimal('2.675'), as Excel sees it\n",[79,614,615],{"class":81,"line":259},[79,616,141],{"emptyLinePlaceholder":140},[79,618,619,621,624],{"class":81,"line":287},[79,620,574],{"class":123},[79,622,623],{"class":577}," _quantum",[79,625,626],{"class":127},"(digits):\n",[79,628,630,632,634,636,639,641,644],{"class":81,"line":629},7,[79,631,586],{"class":123},[79,633,589],{"class":127},[79,635,417],{"class":156},[79,637,638],{"class":127},").scaleb(",[79,640,172],{"class":123},[79,642,643],{"class":127},"digits)                 ",[79,645,646],{"class":611},"# digits=2 -> 0.01, digits=-2 -> 1E+2\n",[79,648,650],{"class":81,"line":649},8,[79,651,141],{"emptyLinePlaceholder":140},[79,653,655,657,660,663,665,667,670,672,674],{"class":81,"line":654},9,[79,656,574],{"class":123},[79,658,659],{"class":577}," excel_round",[79,661,662],{"class":127},"(x, digits",[79,664,150],{"class":123},[79,666,353],{"class":156},[79,668,669],{"class":127},", rule",[79,671,150],{"class":123},[79,673,555],{"class":156},[79,675,676],{"class":127},"):\n",[79,678,680,683,685],{"class":81,"line":679},10,[79,681,682],{"class":127},"    q ",[79,684,150],{"class":123},[79,686,687],{"class":127}," _quantum(digits)\n",[79,689,691,694,696],{"class":81,"line":690},11,[79,692,693],{"class":127},"    d ",[79,695,150],{"class":123},[79,697,698],{"class":127}," _dec(x)\n",[79,700,702,705,708,711,714,717],{"class":81,"line":701},12,[79,703,704],{"class":123},"    if",[79,706,707],{"class":127}," digits ",[79,709,710],{"class":123},"\u003C",[79,712,713],{"class":156}," 0",[79,715,716],{"class":127},":                                     ",[79,718,719],{"class":611},"# round to tens, hundreds, …\n",[79,721,723,726,729,732,735,738,740,743,747,749,752,755],{"class":81,"line":722},13,[79,724,725],{"class":123},"        return",[79,727,728],{"class":156}," float",[79,730,731],{"class":127},"((d ",[79,733,734],{"class":123},"\u002F",[79,736,737],{"class":127}," q).quantize(Decimal(",[79,739,417],{"class":156},[79,741,742],{"class":127},"), ",[79,744,746],{"class":745},"sa561","rounding",[79,748,150],{"class":123},[79,750,751],{"class":127},"rule) ",[79,753,754],{"class":123},"*",[79,756,757],{"class":127}," q)\n",[79,759,761,763,765,768,770,772],{"class":81,"line":760},14,[79,762,586],{"class":123},[79,764,728],{"class":156},[79,766,767],{"class":127},"(d.quantize(q, ",[79,769,746],{"class":745},[79,771,150],{"class":123},[79,773,774],{"class":127},"rule))\n",[79,776,778],{"class":81,"line":777},15,[79,779,141],{"emptyLinePlaceholder":140},[79,781,783,785,788,790,792,794],{"class":81,"line":782},16,[79,784,574],{"class":123},[79,786,787],{"class":577}," excel_roundup",[79,789,662],{"class":127},[79,791,150],{"class":123},[79,793,353],{"class":156},[79,795,676],{"class":127},[79,797,799,801,804,806,809],{"class":81,"line":798},17,[79,800,586],{"class":123},[79,802,803],{"class":127}," excel_round(x, digits, ",[79,805,560],{"class":156},[79,807,808],{"class":127},")            ",[79,810,811],{"class":611},"# away from zero\n",[79,813,815],{"class":81,"line":814},18,[79,816,141],{"emptyLinePlaceholder":140},[79,818,820,822,825,827,829,831],{"class":81,"line":819},19,[79,821,574],{"class":123},[79,823,824],{"class":577}," excel_rounddown",[79,826,662],{"class":127},[79,828,150],{"class":123},[79,830,353],{"class":156},[79,832,676],{"class":127},[79,834,836,838,840,843,846],{"class":81,"line":835},20,[79,837,586],{"class":123},[79,839,803],{"class":127},[79,841,842],{"class":156},"ROUND_DOWN",[79,844,845],{"class":127},")          ",[79,847,848],{"class":611},"# towards zero, i.e. truncate\n",[79,850,852],{"class":81,"line":851},21,[79,853,141],{"emptyLinePlaceholder":140},[79,855,857,859,862,864,866,868,871,873,875,877,879,881,883,885,887,890,892,894,896,899,901,903,905,907,910,912,914,916],{"class":81,"line":856},22,[79,858,198],{"class":156},[79,860,861],{"class":127},"([excel_round(v) ",[79,863,216],{"class":123},[79,865,219],{"class":127},[79,867,222],{"class":123},[79,869,870],{"class":127}," (",[79,872,157],{"class":156},[79,874,40],{"class":127},[79,876,162],{"class":156},[79,878,40],{"class":127},[79,880,167],{"class":156},[79,882,40],{"class":127},[79,884,172],{"class":123},[79,886,167],{"class":156},[79,888,889],{"class":127},")], excel_round(",[79,891,179],{"class":156},[79,893,40],{"class":127},[79,895,239],{"class":156},[79,897,898],{"class":127},"), excel_round(",[79,900,184],{"class":156},[79,902,40],{"class":127},[79,904,239],{"class":156},[79,906,898],{"class":127},[79,908,909],{"class":156},"1234.5",[79,911,40],{"class":127},[79,913,172],{"class":123},[79,915,239],{"class":156},[79,917,918],{"class":127},"))\n",[79,920,922,924,927,930,932,934,937,939,941,943,945,948,950,953,955,957],{"class":81,"line":921},23,[79,923,198],{"class":156},[79,925,926],{"class":127},"(excel_roundup(",[79,928,929],{"class":156},"3.141",[79,931,40],{"class":127},[79,933,239],{"class":156},[79,935,936],{"class":127},"), excel_roundup(",[79,938,172],{"class":123},[79,940,929],{"class":156},[79,942,40],{"class":127},[79,944,239],{"class":156},[79,946,947],{"class":127},"), excel_rounddown(",[79,949,172],{"class":123},[79,951,952],{"class":156},"3.149",[79,954,40],{"class":127},[79,956,239],{"class":156},[79,958,918],{"class":127},[10,960,961,963,964,966,967,969,970,973,974,977,978,981,982,53,984,986,987,53,990,993,994,53,996,963,998,1000,1001,1004],{},[14,962,555],{}," in ",[14,965,106],{}," means \"half away from zero\", so it handles negatives the way Excel does. The ",[14,968,601],{}," conversion is the important detail: ",[14,971,972],{},"Decimal(2.675)"," directly would capture the binary value 2.67499…, while ",[14,975,976],{},"Decimal(\"2.675\")"," is the number the user typed and Excel displays. Negative digits round to the left of the decimal point — ",[14,979,980],{},"ROUND(1234.5, -2)"," is 1200. ",[14,983,43],{},[14,985,46],{}," in Excel round ",[27,988,989],{},"away from",[27,991,992],{},"towards"," zero respectively, which are ",[14,995,560],{},[14,997,842],{},[14,999,106],{}," — not the same as ceiling and floor for negative numbers: ",[14,1002,1003],{},"ROUNDUP(-3.141, 2)"," is −3.15.",[65,1006,1008],{"id":1007},"step-3-mround-ceiling-and-floor","Step 3 — MROUND, CEILING and FLOOR",[10,1010,1011,1013,1014,53,1016,1018],{},[14,1012,49],{}," rounds to the nearest multiple — prices to 5 cents, times to 15 minutes, pack quantities to 12. ",[14,1015,52],{},[14,1017,56],{}," round up or down to a multiple:",[70,1020,1022],{"className":114,"code":1021,"language":116,"meta":75,"style":75},"from decimal import ROUND_CEILING, ROUND_FLOOR\n\ndef excel_mround(x, multiple):\n    if x * multiple \u003C 0:\n        raise ValueError(\"MROUND needs number and multiple with the same sign (Excel returns #NUM!)\")\n    m = _dec(multiple)\n    return float((_dec(x) \u002F m).quantize(Decimal(1), rounding=ROUND_HALF_UP) * m)\n\ndef excel_ceiling_math(x, significance=1):\n    s = _dec(abs(significance))\n    return float((_dec(x) \u002F s).quantize(Decimal(1), rounding=ROUND_CEILING) * s)\n\ndef excel_floor_math(x, significance=1):\n    s = _dec(abs(significance))\n    return float((_dec(x) \u002F s).quantize(Decimal(1), rounding=ROUND_FLOOR) * s)\n\nprint(excel_mround(10.07, 0.05), excel_mround(37, 12), excel_mround(0.125, 0.05))\nprint(excel_ceiling_math(4.42, 0.25), excel_ceiling_math(-4.42, 0.25), excel_floor_math(4.42, 0.25), excel_floor_math(-4.42, 0.25))\n",[14,1023,1024,1040,1044,1054,1073,1088,1098,1129,1133,1149,1165,1196,1200,1215,1227,1256,1260,1296],{"__ignoreMap":75},[79,1025,1026,1028,1030,1032,1035,1037],{"class":81,"line":82},[79,1027,544],{"class":123},[79,1029,547],{"class":127},[79,1031,124],{"class":123},[79,1033,1034],{"class":156}," ROUND_CEILING",[79,1036,40],{"class":127},[79,1038,1039],{"class":156},"ROUND_FLOOR\n",[79,1041,1042],{"class":81,"line":137},[79,1043,141],{"emptyLinePlaceholder":140},[79,1045,1046,1048,1051],{"class":81,"line":144},[79,1047,574],{"class":123},[79,1049,1050],{"class":577}," excel_mround",[79,1052,1053],{"class":127},"(x, multiple):\n",[79,1055,1056,1058,1061,1063,1066,1068,1070],{"class":81,"line":195},[79,1057,704],{"class":123},[79,1059,1060],{"class":127}," x ",[79,1062,754],{"class":123},[79,1064,1065],{"class":127}," multiple ",[79,1067,710],{"class":123},[79,1069,713],{"class":156},[79,1071,1072],{"class":127},":\n",[79,1074,1075,1078,1081,1083,1086],{"class":81,"line":259},[79,1076,1077],{"class":123},"        raise",[79,1079,1080],{"class":156}," ValueError",[79,1082,201],{"class":127},[79,1084,1085],{"class":89},"\"MROUND needs number and multiple with the same sign (Excel returns #NUM!)\"",[79,1087,319],{"class":127},[79,1089,1090,1093,1095],{"class":81,"line":287},[79,1091,1092],{"class":127},"    m ",[79,1094,150],{"class":123},[79,1096,1097],{"class":127}," _dec(multiple)\n",[79,1099,1100,1102,1104,1107,1109,1112,1114,1116,1118,1120,1122,1124,1126],{"class":81,"line":629},[79,1101,586],{"class":123},[79,1103,728],{"class":156},[79,1105,1106],{"class":127},"((_dec(x) ",[79,1108,734],{"class":123},[79,1110,1111],{"class":127}," m).quantize(Decimal(",[79,1113,417],{"class":156},[79,1115,742],{"class":127},[79,1117,746],{"class":745},[79,1119,150],{"class":123},[79,1121,555],{"class":156},[79,1123,242],{"class":127},[79,1125,754],{"class":123},[79,1127,1128],{"class":127}," m)\n",[79,1130,1131],{"class":81,"line":649},[79,1132,141],{"emptyLinePlaceholder":140},[79,1134,1135,1137,1140,1143,1145,1147],{"class":81,"line":654},[79,1136,574],{"class":123},[79,1138,1139],{"class":577}," excel_ceiling_math",[79,1141,1142],{"class":127},"(x, significance",[79,1144,150],{"class":123},[79,1146,417],{"class":156},[79,1148,676],{"class":127},[79,1150,1151,1154,1156,1159,1162],{"class":81,"line":679},[79,1152,1153],{"class":127},"    s ",[79,1155,150],{"class":123},[79,1157,1158],{"class":127}," _dec(",[79,1160,1161],{"class":156},"abs",[79,1163,1164],{"class":127},"(significance))\n",[79,1166,1167,1169,1171,1173,1175,1178,1180,1182,1184,1186,1189,1191,1193],{"class":81,"line":690},[79,1168,586],{"class":123},[79,1170,728],{"class":156},[79,1172,1106],{"class":127},[79,1174,734],{"class":123},[79,1176,1177],{"class":127}," s).quantize(Decimal(",[79,1179,417],{"class":156},[79,1181,742],{"class":127},[79,1183,746],{"class":745},[79,1185,150],{"class":123},[79,1187,1188],{"class":156},"ROUND_CEILING",[79,1190,242],{"class":127},[79,1192,754],{"class":123},[79,1194,1195],{"class":127}," s)\n",[79,1197,1198],{"class":81,"line":701},[79,1199,141],{"emptyLinePlaceholder":140},[79,1201,1202,1204,1207,1209,1211,1213],{"class":81,"line":722},[79,1203,574],{"class":123},[79,1205,1206],{"class":577}," excel_floor_math",[79,1208,1142],{"class":127},[79,1210,150],{"class":123},[79,1212,417],{"class":156},[79,1214,676],{"class":127},[79,1216,1217,1219,1221,1223,1225],{"class":81,"line":760},[79,1218,1153],{"class":127},[79,1220,150],{"class":123},[79,1222,1158],{"class":127},[79,1224,1161],{"class":156},[79,1226,1164],{"class":127},[79,1228,1229,1231,1233,1235,1237,1239,1241,1243,1245,1247,1250,1252,1254],{"class":81,"line":777},[79,1230,586],{"class":123},[79,1232,728],{"class":156},[79,1234,1106],{"class":127},[79,1236,734],{"class":123},[79,1238,1177],{"class":127},[79,1240,417],{"class":156},[79,1242,742],{"class":127},[79,1244,746],{"class":745},[79,1246,150],{"class":123},[79,1248,1249],{"class":156},"ROUND_FLOOR",[79,1251,242],{"class":127},[79,1253,754],{"class":123},[79,1255,1195],{"class":127},[79,1257,1258],{"class":81,"line":782},[79,1259,141],{"emptyLinePlaceholder":140},[79,1261,1262,1264,1267,1270,1272,1275,1278,1281,1283,1286,1288,1290,1292,1294],{"class":81,"line":798},[79,1263,198],{"class":156},[79,1265,1266],{"class":127},"(excel_mround(",[79,1268,1269],{"class":156},"10.07",[79,1271,40],{"class":127},[79,1273,1274],{"class":156},"0.05",[79,1276,1277],{"class":127},"), excel_mround(",[79,1279,1280],{"class":156},"37",[79,1282,40],{"class":127},[79,1284,1285],{"class":156},"12",[79,1287,1277],{"class":127},[79,1289,189],{"class":156},[79,1291,40],{"class":127},[79,1293,1274],{"class":156},[79,1295,918],{"class":127},[79,1297,1298,1300,1303,1306,1308,1311,1314,1316,1318,1320,1322,1325,1327,1329,1331,1333,1335,1337,1339,1341],{"class":81,"line":814},[79,1299,198],{"class":156},[79,1301,1302],{"class":127},"(excel_ceiling_math(",[79,1304,1305],{"class":156},"4.42",[79,1307,40],{"class":127},[79,1309,1310],{"class":156},"0.25",[79,1312,1313],{"class":127},"), excel_ceiling_math(",[79,1315,172],{"class":123},[79,1317,1305],{"class":156},[79,1319,40],{"class":127},[79,1321,1310],{"class":156},[79,1323,1324],{"class":127},"), excel_floor_math(",[79,1326,1305],{"class":156},[79,1328,40],{"class":127},[79,1330,1310],{"class":156},[79,1332,1324],{"class":127},[79,1334,172],{"class":123},[79,1336,1305],{"class":156},[79,1338,40],{"class":127},[79,1340,1310],{"class":156},[79,1342,918],{"class":127},[10,1344,1345,1346,1349,1350,1352,1353,1355,1356,1359,1360,1363,1364,53,1367,1370,1371,53,1373,1375],{},"Dividing by the multiple, rounding to a whole number and multiplying back works for any multiple, and doing it in ",[14,1347,1348],{},"Decimal"," avoids results like 10.049999999 for 10.05. ",[14,1351,49],{}," breaks ties away from zero like ",[14,1354,24],{},", and returns ",[14,1357,1358],{},"#NUM!"," in Excel when the number and the multiple have different signs, mirrored here with a ",[14,1361,1362],{},"ValueError",". ",[14,1365,1366],{},"CEILING.MATH",[14,1368,1369],{},"FLOOR.MATH"," round towards positive and negative infinity by default, so the ceiling of −4.42 to a quarter is −4.25, not −4.5. The older ",[14,1372,52],{},[14,1374,56],{}," functions differ for negative numbers and are best avoided in new workbooks.",[332,1377,341,1382,341,1385,341,1388,341,1391,341,1397,341,1408,341,1413,341,1418,341,1422,341,1426,341,1430,341,1434,341,1439,341,1446,341,1451,341,1455,341,1458,341,1461,341,1464],{"viewBox":1378,"role":335,"ariaLabelledBy":1379,"xmlns":339,"style":340},"4 0 752 233",[1380,1381],"rd-updown-t","rd-updown-d",[343,1383,1384],{"id":1380},"ROUNDUP and ROUNDDOWN versus CEILING and FLOOR",[347,1386,1387],{"id":1381},"ROUNDUP and ROUNDDOWN move away from or towards zero, so for negative numbers ROUNDUP goes more negative. CEILING.MATH and FLOOR.MATH move towards positive or negative infinity, so the ceiling of a negative number is closer to zero.",[351,1389],{"x":228,"y":353,"width":354,"height":1390,"fill":356},"233",[351,1392],{"x":359,"y":360,"width":1393,"height":1394,"rx":1395,"fill":369,"stroke":370,"style":1396},"351.0","201.0","14","stroke-width:2px",[1398,1399,1401],"g",{"transform":1400},"translate(182.5,29.0) scale(1.083)",[1402,1403],"path",{"d":1404,"fill":1405,"stroke":1406,"style":1407},"M5 9h14 M4 15h14 M10 4l-2 16 M16 4l-2 16","none","var(--brand-strong,#4338ca)","stroke-width:1.66px;stroke-linecap:round;stroke-linejoin:round",[373,1409,1412],{"x":1410,"y":401,"style":1411},"195.5","font-size:14px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","ROUNDUP \u002F ROUNDDOWN",[81,1414],{"x1":1415,"y1":1416,"x2":1417,"y2":1416,"stroke":370,"style":364},"36.0","91.0","355.0",[373,1419,1421],{"x":1410,"y":427,"style":1420},"font-size:12px;font-weight:400;fill:var(--text,#172033);text-anchor:middle","away from \u002F towards zero",[373,1423,1425],{"x":1410,"y":1424,"style":1420},"137.0","ROUNDUP(-3.141, 2) = -3.15",[373,1427,1429],{"x":1410,"y":1428,"style":1420},"163.0","decimal ROUND_UP \u002F ROUND_DOWN",[373,1431,1433],{"x":1410,"y":1432,"style":1420},"189.0","digits argument",[351,1435],{"x":1436,"y":360,"width":1393,"height":1394,"rx":1395,"fill":1437,"stroke":1438,"style":1396},"389.0","#d9f4f1","var(--teal,#0f9488)",[1398,1440,1442],{"transform":1441},"translate(551.5,29.0) scale(1.083)",[1402,1443],{"d":1444,"fill":1405,"stroke":1445,"style":1407},"M12 3l9 5-9 5-9-5z M3 13l9 5 9-5 M3 17l9 5 9-5","var(--teal-ink,#0b6157)",[373,1447,1450],{"x":1448,"y":401,"style":1449},"564.5","font-size:14px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","CEILING.MATH \u002F FLOOR.MATH",[81,1452],{"x1":1453,"y1":1416,"x2":1454,"y2":1416,"stroke":1438,"style":364},"405.0","724.0",[373,1456,1457],{"x":1448,"y":427,"style":1420},"towards +∞ \u002F −∞",[373,1459,1460],{"x":1448,"y":1424,"style":1420},"CEILING(-4.42, 0.25) = -4.25",[373,1462,1463],{"x":1448,"y":1428,"style":1420},"decimal ROUND_CEILING \u002F ROUND_FLOOR",[373,1465,1466],{"x":1448,"y":1432,"style":1420},"significance argument",[65,1468,1470],{"id":1469},"step-4-check-every-function-against-a-recalculated-workbook","Step 4 — Check every function against a recalculated workbook",[70,1472,1474],{"className":114,"code":1473,"language":116,"meta":75,"style":75},"import subprocess\nfrom openpyxl import Workbook, load_workbook\n\ncases = [(\"ROUND\", v, d) for v in (0.5, 1.5, 2.5, -2.5, 2.675, 1.005, 0.125, -0.125, 1234.5, 149.99) for d in (0, 2, -1)]\ncases += [(\"ROUNDUP\", v, d) for v in (3.141, -3.141, 2.001, -0.0001) for d in (0, 2)]\ncases += [(\"ROUNDDOWN\", v, d) for v in (3.149, -3.149, 2.999) for d in (0, 2)]\ncases += [(\"MROUND\", v, m) for v, m in ((10.07, 0.05), (37, 12), (0.125, 0.05), (7.5, 5), (-7.5, -5), (1.23, 0.1))]\ncases += [(\"CEILING.MATH\", v, s) for v, s in ((4.42, 0.25), (-4.42, 0.25), (2.0, 1), (0.1, 0.05))]\ncases += [(\"FLOOR.MATH\", v, s) for v, s in ((4.42, 0.25), (-4.42, 0.25), (2.999, 1))]\nPY = {\"ROUND\": excel_round, \"ROUNDUP\": excel_roundup, \"ROUNDDOWN\": excel_rounddown, \"MROUND\": excel_mround,\n      \"CEILING.MATH\": excel_ceiling_math, \"FLOOR.MATH\": excel_floor_math}\n\nwb = Workbook()\nws = wb.active\nfor i, (fn, v, a) in enumerate(cases, start=1):\n    name = f\"_xlfn.{fn}\" if fn.endswith(\".MATH\") else fn\n    ws.append([fn, v, a, f\"={name}(B{i},C{i})\"])\nwb.save(\"rounding.xlsx\")\nsubprocess.run([\"soffice\", \"--headless\", \"--convert-to\", \"xlsx\", \"--outdir\", \"calc\", \"rounding.xlsx\"], check=True, capture_output=True)\ncalc = load_workbook(\"calc\u002Frounding.xlsx\", data_only=True).active\nmismatch = [(fn, v, a, calc[f\"D{i}\"].value, PY[fn](v, a)) for i, (fn, v, a) in enumerate(cases, start=1)\n            if abs(calc[f\"D{i}\"].value - PY[fn](v, a)) > 1e-9]\nprint(f\"{len(cases)} cases compared, {len(mismatch)} mismatches\")\nprint(\"Python's built-in round disagrees on\", sum(1 for i, (fn, v, a) in enumerate(cases, 1)\n      if fn == \"ROUND\" and abs(calc[f\"D{i}\"].value - round(v, a)) > 1e-9), \"of the ROUND cases\")\n",[14,1475,1476,1483,1495,1499,1592,1652,1704,1786,1844,1891,1922,1935,1939,1949,1959,1983,2022,2064,2074,2133,2158,2207,2248,2285,2319],{"__ignoreMap":75},[79,1477,1478,1480],{"class":81,"line":82},[79,1479,124],{"class":123},[79,1481,1482],{"class":127}," subprocess\n",[79,1484,1485,1487,1490,1492],{"class":81,"line":137},[79,1486,544],{"class":123},[79,1488,1489],{"class":127}," openpyxl ",[79,1491,124],{"class":123},[79,1493,1494],{"class":127}," Workbook, load_workbook\n",[79,1496,1497],{"class":81,"line":144},[79,1498,141],{"emptyLinePlaceholder":140},[79,1500,1501,1504,1506,1509,1512,1515,1517,1519,1521,1523,1525,1527,1529,1531,1533,1535,1537,1539,1541,1543,1545,1547,1549,1551,1553,1555,1557,1559,1561,1563,1566,1568,1570,1573,1575,1577,1579,1581,1583,1585,1587,1589],{"class":81,"line":195},[79,1502,1503],{"class":127},"cases ",[79,1505,150],{"class":123},[79,1507,1508],{"class":127}," [(",[79,1510,1511],{"class":89},"\"ROUND\"",[79,1513,1514],{"class":127},", v, d) ",[79,1516,216],{"class":123},[79,1518,219],{"class":127},[79,1520,222],{"class":123},[79,1522,870],{"class":127},[79,1524,157],{"class":156},[79,1526,40],{"class":127},[79,1528,162],{"class":156},[79,1530,40],{"class":127},[79,1532,167],{"class":156},[79,1534,40],{"class":127},[79,1536,172],{"class":123},[79,1538,167],{"class":156},[79,1540,40],{"class":127},[79,1542,179],{"class":156},[79,1544,40],{"class":127},[79,1546,184],{"class":156},[79,1548,40],{"class":127},[79,1550,189],{"class":156},[79,1552,40],{"class":127},[79,1554,172],{"class":123},[79,1556,189],{"class":156},[79,1558,40],{"class":127},[79,1560,909],{"class":156},[79,1562,40],{"class":127},[79,1564,1565],{"class":156},"149.99",[79,1567,242],{"class":127},[79,1569,216],{"class":123},[79,1571,1572],{"class":127}," d ",[79,1574,222],{"class":123},[79,1576,870],{"class":127},[79,1578,353],{"class":156},[79,1580,40],{"class":127},[79,1582,239],{"class":156},[79,1584,40],{"class":127},[79,1586,172],{"class":123},[79,1588,417],{"class":156},[79,1590,1591],{"class":127},")]\n",[79,1593,1594,1596,1599,1601,1604,1606,1608,1610,1612,1614,1616,1618,1620,1622,1624,1627,1629,1631,1634,1636,1638,1640,1642,1644,1646,1648,1650],{"class":81,"line":259},[79,1595,1503],{"class":127},[79,1597,1598],{"class":123},"+=",[79,1600,1508],{"class":127},[79,1602,1603],{"class":89},"\"ROUNDUP\"",[79,1605,1514],{"class":127},[79,1607,216],{"class":123},[79,1609,219],{"class":127},[79,1611,222],{"class":123},[79,1613,870],{"class":127},[79,1615,929],{"class":156},[79,1617,40],{"class":127},[79,1619,172],{"class":123},[79,1621,929],{"class":156},[79,1623,40],{"class":127},[79,1625,1626],{"class":156},"2.001",[79,1628,40],{"class":127},[79,1630,172],{"class":123},[79,1632,1633],{"class":156},"0.0001",[79,1635,242],{"class":127},[79,1637,216],{"class":123},[79,1639,1572],{"class":127},[79,1641,222],{"class":123},[79,1643,870],{"class":127},[79,1645,353],{"class":156},[79,1647,40],{"class":127},[79,1649,239],{"class":156},[79,1651,1591],{"class":127},[79,1653,1654,1656,1658,1660,1663,1665,1667,1669,1671,1673,1675,1677,1679,1681,1683,1686,1688,1690,1692,1694,1696,1698,1700,1702],{"class":81,"line":287},[79,1655,1503],{"class":127},[79,1657,1598],{"class":123},[79,1659,1508],{"class":127},[79,1661,1662],{"class":89},"\"ROUNDDOWN\"",[79,1664,1514],{"class":127},[79,1666,216],{"class":123},[79,1668,219],{"class":127},[79,1670,222],{"class":123},[79,1672,870],{"class":127},[79,1674,952],{"class":156},[79,1676,40],{"class":127},[79,1678,172],{"class":123},[79,1680,952],{"class":156},[79,1682,40],{"class":127},[79,1684,1685],{"class":156},"2.999",[79,1687,242],{"class":127},[79,1689,216],{"class":123},[79,1691,1572],{"class":127},[79,1693,222],{"class":123},[79,1695,870],{"class":127},[79,1697,353],{"class":156},[79,1699,40],{"class":127},[79,1701,239],{"class":156},[79,1703,1591],{"class":127},[79,1705,1706,1708,1710,1712,1715,1718,1720,1723,1725,1728,1730,1732,1734,1737,1739,1741,1743,1745,1747,1749,1751,1753,1756,1758,1761,1763,1765,1767,1769,1771,1773,1775,1778,1780,1783],{"class":81,"line":629},[79,1707,1503],{"class":127},[79,1709,1598],{"class":123},[79,1711,1508],{"class":127},[79,1713,1714],{"class":89},"\"MROUND\"",[79,1716,1717],{"class":127},", v, m) ",[79,1719,216],{"class":123},[79,1721,1722],{"class":127}," v, m ",[79,1724,222],{"class":123},[79,1726,1727],{"class":127}," ((",[79,1729,1269],{"class":156},[79,1731,40],{"class":127},[79,1733,1274],{"class":156},[79,1735,1736],{"class":127},"), (",[79,1738,1280],{"class":156},[79,1740,40],{"class":127},[79,1742,1285],{"class":156},[79,1744,1736],{"class":127},[79,1746,189],{"class":156},[79,1748,40],{"class":127},[79,1750,1274],{"class":156},[79,1752,1736],{"class":127},[79,1754,1755],{"class":156},"7.5",[79,1757,40],{"class":127},[79,1759,1760],{"class":156},"5",[79,1762,1736],{"class":127},[79,1764,172],{"class":123},[79,1766,1755],{"class":156},[79,1768,40],{"class":127},[79,1770,172],{"class":123},[79,1772,1760],{"class":156},[79,1774,1736],{"class":127},[79,1776,1777],{"class":156},"1.23",[79,1779,40],{"class":127},[79,1781,1782],{"class":156},"0.1",[79,1784,1785],{"class":127},"))]\n",[79,1787,1788,1790,1792,1794,1797,1800,1802,1805,1807,1809,1811,1813,1815,1817,1819,1821,1823,1825,1827,1830,1832,1834,1836,1838,1840,1842],{"class":81,"line":649},[79,1789,1503],{"class":127},[79,1791,1598],{"class":123},[79,1793,1508],{"class":127},[79,1795,1796],{"class":89},"\"CEILING.MATH\"",[79,1798,1799],{"class":127},", v, s) ",[79,1801,216],{"class":123},[79,1803,1804],{"class":127}," v, s ",[79,1806,222],{"class":123},[79,1808,1727],{"class":127},[79,1810,1305],{"class":156},[79,1812,40],{"class":127},[79,1814,1310],{"class":156},[79,1816,1736],{"class":127},[79,1818,172],{"class":123},[79,1820,1305],{"class":156},[79,1822,40],{"class":127},[79,1824,1310],{"class":156},[79,1826,1736],{"class":127},[79,1828,1829],{"class":156},"2.0",[79,1831,40],{"class":127},[79,1833,417],{"class":156},[79,1835,1736],{"class":127},[79,1837,1782],{"class":156},[79,1839,40],{"class":127},[79,1841,1274],{"class":156},[79,1843,1785],{"class":127},[79,1845,1846,1848,1850,1852,1855,1857,1859,1861,1863,1865,1867,1869,1871,1873,1875,1877,1879,1881,1883,1885,1887,1889],{"class":81,"line":654},[79,1847,1503],{"class":127},[79,1849,1598],{"class":123},[79,1851,1508],{"class":127},[79,1853,1854],{"class":89},"\"FLOOR.MATH\"",[79,1856,1799],{"class":127},[79,1858,216],{"class":123},[79,1860,1804],{"class":127},[79,1862,222],{"class":123},[79,1864,1727],{"class":127},[79,1866,1305],{"class":156},[79,1868,40],{"class":127},[79,1870,1310],{"class":156},[79,1872,1736],{"class":127},[79,1874,172],{"class":123},[79,1876,1305],{"class":156},[79,1878,40],{"class":127},[79,1880,1310],{"class":156},[79,1882,1736],{"class":127},[79,1884,1685],{"class":156},[79,1886,40],{"class":127},[79,1888,417],{"class":156},[79,1890,1785],{"class":127},[79,1892,1893,1896,1899,1902,1904,1907,1909,1912,1914,1917,1919],{"class":81,"line":679},[79,1894,1895],{"class":156},"PY",[79,1897,1898],{"class":123}," =",[79,1900,1901],{"class":127}," {",[79,1903,1511],{"class":89},[79,1905,1906],{"class":127},": excel_round, ",[79,1908,1603],{"class":89},[79,1910,1911],{"class":127},": excel_roundup, ",[79,1913,1662],{"class":89},[79,1915,1916],{"class":127},": excel_rounddown, ",[79,1918,1714],{"class":89},[79,1920,1921],{"class":127},": excel_mround,\n",[79,1923,1924,1927,1930,1932],{"class":81,"line":690},[79,1925,1926],{"class":89},"      \"CEILING.MATH\"",[79,1928,1929],{"class":127},": excel_ceiling_math, ",[79,1931,1854],{"class":89},[79,1933,1934],{"class":127},": excel_floor_math}\n",[79,1936,1937],{"class":81,"line":701},[79,1938,141],{"emptyLinePlaceholder":140},[79,1940,1941,1944,1946],{"class":81,"line":722},[79,1942,1943],{"class":127},"wb ",[79,1945,150],{"class":123},[79,1947,1948],{"class":127}," Workbook()\n",[79,1950,1951,1954,1956],{"class":81,"line":760},[79,1952,1953],{"class":127},"ws ",[79,1955,150],{"class":123},[79,1957,1958],{"class":127}," wb.active\n",[79,1960,1961,1963,1966,1968,1971,1974,1977,1979,1981],{"class":81,"line":777},[79,1962,216],{"class":123},[79,1964,1965],{"class":127}," i, (fn, v, a) ",[79,1967,222],{"class":123},[79,1969,1970],{"class":156}," enumerate",[79,1972,1973],{"class":127},"(cases, ",[79,1975,1976],{"class":745},"start",[79,1978,150],{"class":123},[79,1980,417],{"class":156},[79,1982,676],{"class":127},[79,1984,1985,1988,1990,1993,1996,1998,2001,2003,2005,2008,2011,2014,2016,2019],{"class":81,"line":782},[79,1986,1987],{"class":127},"    name ",[79,1989,150],{"class":123},[79,1991,1992],{"class":123}," f",[79,1994,1995],{"class":89},"\"_xlfn.",[79,1997,306],{"class":305},[79,1999,2000],{"class":127},"fn",[79,2002,314],{"class":305},[79,2004,302],{"class":89},[79,2006,2007],{"class":123}," if",[79,2009,2010],{"class":127}," fn.endswith(",[79,2012,2013],{"class":89},"\".MATH\"",[79,2015,242],{"class":127},[79,2017,2018],{"class":123},"else",[79,2020,2021],{"class":127}," fn\n",[79,2023,2024,2027,2029,2032,2034,2037,2039,2042,2044,2047,2049,2052,2054,2056,2058,2061],{"class":81,"line":798},[79,2025,2026],{"class":127},"    ws.append([fn, v, a, ",[79,2028,299],{"class":123},[79,2030,2031],{"class":89},"\"=",[79,2033,306],{"class":305},[79,2035,2036],{"class":127},"name",[79,2038,314],{"class":305},[79,2040,2041],{"class":89},"(B",[79,2043,306],{"class":305},[79,2045,2046],{"class":127},"i",[79,2048,314],{"class":305},[79,2050,2051],{"class":89},",C",[79,2053,306],{"class":305},[79,2055,2046],{"class":127},[79,2057,314],{"class":305},[79,2059,2060],{"class":89},")\"",[79,2062,2063],{"class":127},"])\n",[79,2065,2066,2069,2072],{"class":81,"line":814},[79,2067,2068],{"class":127},"wb.save(",[79,2070,2071],{"class":89},"\"rounding.xlsx\"",[79,2073,319],{"class":127},[79,2075,2076,2079,2082,2084,2087,2089,2092,2094,2097,2099,2102,2104,2107,2109,2111,2114,2117,2119,2122,2124,2127,2129,2131],{"class":81,"line":819},[79,2077,2078],{"class":127},"subprocess.run([",[79,2080,2081],{"class":89},"\"soffice\"",[79,2083,40],{"class":127},[79,2085,2086],{"class":89},"\"--headless\"",[79,2088,40],{"class":127},[79,2090,2091],{"class":89},"\"--convert-to\"",[79,2093,40],{"class":127},[79,2095,2096],{"class":89},"\"xlsx\"",[79,2098,40],{"class":127},[79,2100,2101],{"class":89},"\"--outdir\"",[79,2103,40],{"class":127},[79,2105,2106],{"class":89},"\"calc\"",[79,2108,40],{"class":127},[79,2110,2071],{"class":89},[79,2112,2113],{"class":127},"], ",[79,2115,2116],{"class":745},"check",[79,2118,150],{"class":123},[79,2120,2121],{"class":156},"True",[79,2123,40],{"class":127},[79,2125,2126],{"class":745},"capture_output",[79,2128,150],{"class":123},[79,2130,2121],{"class":156},[79,2132,319],{"class":127},[79,2134,2135,2138,2140,2143,2146,2148,2151,2153,2155],{"class":81,"line":835},[79,2136,2137],{"class":127},"calc ",[79,2139,150],{"class":123},[79,2141,2142],{"class":127}," load_workbook(",[79,2144,2145],{"class":89},"\"calc\u002Frounding.xlsx\"",[79,2147,40],{"class":127},[79,2149,2150],{"class":745},"data_only",[79,2152,150],{"class":123},[79,2154,2121],{"class":156},[79,2156,2157],{"class":127},").active\n",[79,2159,2160,2163,2165,2168,2170,2173,2175,2177,2179,2181,2184,2186,2189,2191,2193,2195,2197,2199,2201,2203,2205],{"class":81,"line":851},[79,2161,2162],{"class":127},"mismatch ",[79,2164,150],{"class":123},[79,2166,2167],{"class":127}," [(fn, v, a, calc[",[79,2169,299],{"class":123},[79,2171,2172],{"class":89},"\"D",[79,2174,306],{"class":305},[79,2176,2046],{"class":127},[79,2178,314],{"class":305},[79,2180,302],{"class":89},[79,2182,2183],{"class":127},"].value, ",[79,2185,1895],{"class":156},[79,2187,2188],{"class":127},"[fn](v, a)) ",[79,2190,216],{"class":123},[79,2192,1965],{"class":127},[79,2194,222],{"class":123},[79,2196,1970],{"class":156},[79,2198,1973],{"class":127},[79,2200,1976],{"class":745},[79,2202,150],{"class":123},[79,2204,417],{"class":156},[79,2206,319],{"class":127},[79,2208,2209,2212,2215,2218,2220,2222,2224,2226,2228,2230,2233,2235,2238,2240,2243,2246],{"class":81,"line":856},[79,2210,2211],{"class":123},"            if",[79,2213,2214],{"class":156}," abs",[79,2216,2217],{"class":127},"(calc[",[79,2219,299],{"class":123},[79,2221,2172],{"class":89},[79,2223,306],{"class":305},[79,2225,2046],{"class":127},[79,2227,314],{"class":305},[79,2229,302],{"class":89},[79,2231,2232],{"class":127},"].value ",[79,2234,172],{"class":123},[79,2236,2237],{"class":156}," PY",[79,2239,2188],{"class":127},[79,2241,2242],{"class":123},">",[79,2244,2245],{"class":156}," 1e-9",[79,2247,192],{"class":127},[79,2249,2250,2252,2254,2256,2258,2260,2263,2266,2268,2271,2273,2275,2278,2280,2283],{"class":81,"line":921},[79,2251,198],{"class":156},[79,2253,201],{"class":127},[79,2255,299],{"class":123},[79,2257,302],{"class":89},[79,2259,306],{"class":305},[79,2261,2262],{"class":156},"len",[79,2264,2265],{"class":127},"(cases)",[79,2267,314],{"class":305},[79,2269,2270],{"class":89}," cases compared, ",[79,2272,306],{"class":305},[79,2274,2262],{"class":156},[79,2276,2277],{"class":127},"(mismatch)",[79,2279,314],{"class":305},[79,2281,2282],{"class":89}," mismatches\"",[79,2284,319],{"class":127},[79,2286,2288,2290,2292,2295,2297,2300,2302,2304,2307,2309,2311,2313,2315,2317],{"class":81,"line":2287},24,[79,2289,198],{"class":156},[79,2291,201],{"class":127},[79,2293,2294],{"class":89},"\"Python's built-in round disagrees on\"",[79,2296,40],{"class":127},[79,2298,2299],{"class":156},"sum",[79,2301,201],{"class":127},[79,2303,417],{"class":156},[79,2305,2306],{"class":123}," for",[79,2308,1965],{"class":127},[79,2310,222],{"class":123},[79,2312,1970],{"class":156},[79,2314,1973],{"class":127},[79,2316,417],{"class":156},[79,2318,319],{"class":127},[79,2320,2322,2325,2328,2331,2334,2337,2339,2341,2343,2345,2347,2349,2351,2353,2355,2357,2360,2363,2365,2367,2369,2372],{"class":81,"line":2321},25,[79,2323,2324],{"class":123},"      if",[79,2326,2327],{"class":127}," fn ",[79,2329,2330],{"class":123},"==",[79,2332,2333],{"class":89}," \"ROUND\"",[79,2335,2336],{"class":123}," and",[79,2338,2214],{"class":156},[79,2340,2217],{"class":127},[79,2342,299],{"class":123},[79,2344,2172],{"class":89},[79,2346,306],{"class":305},[79,2348,2046],{"class":127},[79,2350,314],{"class":305},[79,2352,302],{"class":89},[79,2354,2232],{"class":127},[79,2356,172],{"class":123},[79,2358,2359],{"class":156}," round",[79,2361,2362],{"class":127},"(v, a)) ",[79,2364,2242],{"class":123},[79,2366,2245],{"class":156},[79,2368,742],{"class":127},[79,2370,2371],{"class":89},"\"of the ROUND cases\"",[79,2373,319],{"class":127},[10,2375,2376,2377,2379,2380,2382,2383,2385],{},"Every case — ties, negative numbers, negative digits, binary-unfriendly values such as 2.675 and 1.005, multiples and significances — gives the same result in Python as in the recalculated workbook, while Python's built-in ",[14,2378,210],{}," disagrees with Excel on a good share of the ",[14,2381,24],{}," cases. Keeping such a comparison as a test protects the functions from a well-meant \"simplification\" back to ",[14,2384,16],{}," later.",[332,2387,341,2392,341,2395,341,2398,341,2401,341,2405,341,2412,341,2418,341,2422,341,2427,341,2432,341,2435,341,2441,341,2447,341,2451,341,2455,341,2459,341,2462,341,2467,341,2474,341,2480,341,2484,341,2487,341,2491,341,2495,341,2498,341,2501,341,2506,341,2511,341,2514,341,2517,341,2521,341,2524,341,2527,341,2533,341,2537],{"viewBox":2388,"role":335,"ariaLabelledBy":2389,"xmlns":339,"style":340},"4 0 752 160",[2390,2391],"rd-recipe-t","rd-recipe-d",[343,2393,2394],{"id":2390},"Rounding a float the way Excel does",[347,2396,2397],{"id":2391},"Take the float, convert it to a Decimal through its 15-significant-digit text so binary artefacts disappear, choose the rounding rule for the Excel function, quantise to the required digits or multiple, and convert back to float.",[351,2399],{"x":228,"y":353,"width":354,"height":2400,"fill":356},"160",[351,2402],{"x":359,"y":360,"width":2403,"height":2404,"rx":1285,"fill":397,"stroke":363,"style":1396},"115.2","128.0",[1398,2406,2408],{"transform":2407},"translate(65.6,46.5) scale(1.000)",[1402,2409],{"d":1404,"fill":1405,"stroke":2410,"style":2411},"var(--text,#172033)","stroke-width:1.80px;stroke-linecap:round;stroke-linejoin:round",[373,2413,2417],{"x":2414,"y":2415,"style":2416},"77.6","93.0","font-size:13.5px;font-weight:700;fill:var(--text,#172033);text-anchor:middle","Float value",[373,2419,2421],{"x":2414,"y":2420,"style":408},"112.5","2.67499999…",[81,2423],{"x1":2424,"y1":2425,"x2":2426,"y2":2425,"stroke":370,"style":1396},"140.2","80.0","162.2",[2428,2429],"polygon",{"points":2430,"fill":2431},"166.2,80.0 157.2,85.0 157.2,75.0","#5b5cf0",[351,2433],{"x":2434,"y":360,"width":2403,"height":2404,"rx":1285,"fill":369,"stroke":370,"style":1396},"171.2",[1398,2436,2438],{"transform":2437},"translate(216.8,37.8) scale(1.000)",[1402,2439],{"d":2440,"fill":1405,"stroke":1406,"style":2411},"M9 8l-4 4 4 4 M15 8l4 4-4 4",[373,2442,2446],{"x":2443,"y":2444,"style":2445},"228.8","84.2","font-size:13.5px;font-weight:700;fill:var(--brand-strong,#4338ca);text-anchor:middle","Decimal(.15g)",[373,2448,2450],{"x":2443,"y":2449,"style":408},"103.8","2.675, as",[373,2452,2454],{"x":2443,"y":2453,"style":408},"121.2","displayed",[81,2456],{"x1":2457,"y1":2425,"x2":2458,"y2":2425,"stroke":370,"style":1396},"291.4","313.4",[2428,2460],{"points":2461,"fill":2431},"317.4,80.0 308.4,85.0 308.4,75.0",[351,2463],{"x":2464,"y":360,"width":2403,"height":2404,"rx":1285,"fill":2465,"stroke":2466,"style":1396},"322.4","#fdefd8","var(--gold,#b4740a)",[1398,2468,2470],{"transform":2469},"translate(368.0,29.0) scale(1.000)",[1402,2471],{"d":2472,"fill":1405,"stroke":2473,"style":2411},"M3 5h18l-7 8v6l-4 2v-8z","var(--gold-ink,#7a4e06)",[373,2475,2479],{"x":2476,"y":2477,"style":2478},"380.0","75.5","font-size:13.5px;font-weight:700;fill:var(--gold-ink,#7a4e06);text-anchor:middle","Pick the rule",[373,2481,2483],{"x":2476,"y":2482,"style":408},"95.0","HALF_UP, UP,",[373,2485,2486],{"x":2476,"y":2420,"style":408},"DOWN,",[373,2488,2490],{"x":2476,"y":2489,"style":408},"130.0","CEILING…",[81,2492],{"x1":2493,"y1":2425,"x2":2494,"y2":2425,"stroke":370,"style":1396},"442.6","464.6",[2428,2496],{"points":2497,"fill":2431},"468.6,80.0 459.6,85.0 459.6,75.0",[351,2499],{"x":2500,"y":360,"width":2403,"height":2404,"rx":1285,"fill":1437,"stroke":1438,"style":1396},"473.6",[1398,2502,2504],{"transform":2503},"translate(519.2,37.8) scale(1.000)",[1402,2505],{"d":1444,"fill":1405,"stroke":1445,"style":2411},[373,2507,2510],{"x":2508,"y":2444,"style":2509},"531.2","font-size:13.5px;font-weight:700;fill:var(--teal-ink,#0b6157);text-anchor:middle","quantize",[373,2512,2513],{"x":2508,"y":2449,"style":408},"digits or",[373,2515,2516],{"x":2508,"y":2453,"style":408},"multiple",[81,2518],{"x1":2519,"y1":2425,"x2":2520,"y2":2425,"stroke":370,"style":1396},"593.8","615.8",[2428,2522],{"points":2523,"fill":2431},"619.8,80.0 610.8,85.0 610.8,75.0",[351,2525],{"x":2526,"y":360,"width":2403,"height":2404,"rx":1285,"fill":1437,"stroke":1438,"style":1396},"624.8",[1398,2528,2530],{"transform":2529},"translate(670.4,46.5) scale(1.000)",[1402,2531],{"d":2532,"fill":1405,"stroke":1445,"style":2411},"M5 12.5l4.5 4.5L19 7",[373,2534,2536],{"x":2535,"y":2415,"style":2509},"682.4","Back to float",[373,2538,476],{"x":2535,"y":2420,"style":408},[65,2540,2542],{"id":2541},"applying-them-to-a-dataframe","Applying them to a DataFrame",[10,2544,2545,2546,2549,2550,2552,2553,2555,2556,2559,2560,2563,2564,63],{},"These functions work value by value, which is fine for invoice totals and a few thousand rows. For a large column, apply them with ",[14,2547,2548],{},"Series.map(lambda v: excel_round(v, 2))","; it is slower than pandas' vectorised ",[14,2551,20],{}," but correct, and correctness is the point when the figures must match a spreadsheet to the penny. Where exact decimal arithmetic matters throughout — summing many amounts and then rounding — keep the values as ",[14,2554,1348],{}," objects in an ",[14,2557,2558],{},"object"," column until the final rounding, rather than converting back to float in between, so the rounding happens on the exact total. And decide ",[27,2561,2562],{},"where"," to round: rounding each line and summing gives a different total from summing and then rounding, and the spreadsheet you are matching has made one of those choices — reproduce the same one. The related question of displaying versus storing rounded values is covered in ",[59,2565,2567],{"href":2566},"\u002Fgetting-started-with-python-excel-automation\u002Fwriting-dataframes-to-excel-with-pandas\u002Fround-numbers-for-excel-output-float-format-vs-number-formats\u002F","Round Numbers for Excel Output: float_format vs Number Formats",[65,2569,2571],{"id":2570},"common-pitfalls","Common pitfalls",[2573,2574,2575,2586,2597,2603,2619],"ul",{},[2576,2577,2578,2585],"li",{},[2579,2580,2581,2582,2584],"strong",{},"Using ",[14,2583,16],{}," to match Excel."," It rounds halves to even; Excel rounds them away from zero.",[2576,2587,2588,2593,2594,63],{},[2579,2589,2590,2592],{},[14,2591,972],{}," from a float."," It captures the binary error; go through ",[14,2595,2596],{},"f\"{x:.15g}\"",[2576,2598,2599,2602],{},[2579,2600,2601],{},"Treating ROUNDUP as ceiling."," For negatives, ROUNDUP moves away from zero.",[2576,2604,2605,2608,2609,2612,2613,2616,2617,63],{},[2579,2606,2607],{},"Float arithmetic for multiples."," ",[14,2610,2611],{},"10.05"," can come out as ",[14,2614,2615],{},"10.049999…","; compute in ",[14,2618,1348],{},[2576,2620,2621,2624],{},[2579,2622,2623],{},"Rounding at a different stage."," Line-level and total-level rounding give different totals.",[65,2626,2628],{"id":2627},"conclusion","Conclusion",[10,2630,2631,2632,2634,2635,2637,2638,2640,2641,2644,2645,2647,2648,40,2650,53,2652,2647,2654,53,2656,2658,2659,2661,2662,53,2664,2647,2666,53,2668,2670],{},"Excel's ",[14,2633,24],{}," rounds halves away from zero on the value as displayed, which neither Python's ",[14,2636,16],{}," nor pandas' ",[14,2639,20],{}," does. Convert values with ",[14,2642,2643],{},"Decimal(f\"{x:.15g}\")"," and quantise with ",[14,2646,555],{}," for ",[14,2649,24],{},[14,2651,560],{},[14,2653,842],{},[14,2655,43],{},[14,2657,46],{},", divide by the multiple for ",[14,2660,49],{},", and use ",[14,2663,1188],{},[14,2665,1249],{},[14,2667,1366],{},[14,2669,1369],{},". Check them against a recalculated workbook, and round at the same stage as the spreadsheet you need to match.",[65,2672,2674],{"id":2673},"frequently-asked-questions","Frequently asked questions",[10,2676,2677,2680],{},[2579,2678,2679],{},"Why does Python round 2.5 to 2?","\nPython's round uses round-half-to-even, also called banker's rounding, so 2.5 rounds to 2 and 3.5 to 4; Excel's ROUND gives 3 and 4.",[10,2682,2683,2686],{},[2579,2684,2685],{},"How do I round like Excel in Python?","\nConvert the value with Decimal(f\"{x:.15g}\") and call quantize with ROUND_HALF_UP and the required number of decimal places.",[10,2688,2689,2692],{},[2579,2690,2691],{},"Why does round(2.675, 2) give 2.67?","\n2.675 cannot be stored exactly in binary and is slightly less than 2.675; converting through its 15-digit text form before rounding gives 2.68, as in Excel.",[10,2694,2695,2698],{},[2579,2696,2697],{},"What is the Python equivalent of MROUND?","\nDivide by the multiple, round to a whole number half away from zero, and multiply back, using Decimal to avoid floating-point artefacts.",[65,2700,2702],{"id":2701},"related","Related",[2573,2704,2705,2711,2718,2725],{},[2576,2706,2707,2708,2710],{},"Up one level: ",[59,2709,62],{"href":61}," — Excel functions in Python.",[2576,2712,2713,2717],{},[59,2714,2716],{"href":2715},"\u002Fgetting-started-with-python-excel-automation\u002Ftroubleshooting-common-python-excel-errors\u002Ffix-floating-point-noise-in-excel-output\u002F","Fix Floating-Point Noise in Excel Output"," — the binary representation problem.",[2576,2719,2720,2724],{},[59,2721,2723],{"href":2722},"\u002Fadvanced-data-transformation-and-cleaning\u002Fworking-with-dates-and-times-in-excel-data\u002Fround-timestamps-into-time-slots-with-pandas\u002F","Round Timestamps into Time Slots with pandas"," — rounding times to multiples.",[2576,2726,2727,2731],{},[59,2728,2730],{"href":2729},"\u002Fautomating-reporting-workflows\u002Fbuilding-finance-and-operations-reports\u002Fbuild-a-vat-return-summary-from-transactions\u002F","Build a VAT Return Summary from Transactions"," — where pennies matter.",[2733,2734,2735],"style",{},"html pre.shiki code .sMTad, html code.shiki .sMTad{--shiki-default:#6F42C1;--shiki-dark:#FFB757}html pre.shiki code .srMev, html code.shiki .srMev{--shiki-default:#032F62;--shiki-dark:#ADDCFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s-kum, html code.shiki .s-kum{--shiki-default:#D73A49;--shiki-dark:#FF9492}html pre.shiki code .skGVy, html code.shiki .skGVy{--shiki-default:#24292E;--shiki-dark:#F0F3F6}html pre.shiki code .sP0c6, html code.shiki .sP0c6{--shiki-default:#005CC5;--shiki-dark:#91CBFF}html pre.shiki code .sSjpA, html code.shiki .sSjpA{--shiki-default:#005CC5;--shiki-dark:#FF9492}html pre.shiki code .s_Opv, html code.shiki .s_Opv{--shiki-default:#6F42C1;--shiki-dark:#DBB7FF}html pre.shiki code .s-wDw, html code.shiki .s-wDw{--shiki-default:#6A737D;--shiki-dark:#BDC4CC}html pre.shiki code .sa561, html code.shiki .sa561{--shiki-default:#E36209;--shiki-dark:#FFB757}",{"title":75,"searchDepth":137,"depth":137,"links":2737},[2738,2739,2740,2741,2742,2743,2744,2745,2746,2747],{"id":67,"depth":137,"text":68},{"id":110,"depth":137,"text":111},{"id":527,"depth":137,"text":528},{"id":1007,"depth":137,"text":1008},{"id":1469,"depth":137,"text":1470},{"id":2541,"depth":137,"text":2542},{"id":2570,"depth":137,"text":2571},{"id":2627,"depth":137,"text":2628},{"id":2673,"depth":137,"text":2674},{"id":2701,"depth":137,"text":2702},"2026-10-02","Reproduce Excel's rounding functions exactly in Python and pandas: why round(2.5) gives 2 and pandas rounds halves to even while Excel's ROUND rounds them away from zero, how floating point turns 2.675 into 2.67, and correct equivalents for ROUND, ROUNDUP, ROUNDDOWN, MROUND, CEILING and FLOOR — including negative digits and negative numbers — checked against a recalculated workbook.","md",[2752,2754,2756,2758],{"q":2679,"a":2753},"Python's round uses round-half-to-even, also called banker's rounding, so 2.5 rounds to 2 and 3.5 to 4; Excel's ROUND gives 3 and 4.",{"q":2685,"a":2755},"Convert the value with Decimal(f\"{x:.15g}\") and call quantize with ROUND_HALF_UP and the required number of decimal places.",{"q":2691,"a":2757},"2.675 cannot be stored exactly in binary and is slightly less than 2.675; converting through its 15-digit text form before rounding gives 2.68, as in Excel.",{"q":2697,"a":2759},"Divide by the multiple, round to a whole number half away from zero, and multiply back, using Decimal to avoid floating-point artefacts.","excel round roundup mround ceiling equivalent python",null,{"breadcrumb":2763},[2764,2766,2769],{"name":2765,"item":734},"Home",{"name":2767,"item":2768},"Advanced Data Transformation and Cleaning for Excel Automation","\u002Fadvanced-data-transformation-and-cleaning\u002F",{"name":62,"item":61},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python",{"title":5,"description":2772},"Excel-identical rounding in Python: half away from zero with Decimal, avoiding float artefacts like 2.675, ROUNDUP and ROUNDDOWN, MROUND to multiples, CEILING and FLOOR, negative digits, vectorised pandas versions and a LibreOffice comparison.","round-roundup-mround-and-ceiling-equivalents-in-python","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Fround-roundup-mround-and-ceiling-equivalents-in-python\u002Findex",[2776,2777],"formula-equivalents","pandas","how-to","uK9x6xLW1x5dsy1ucF477CKNG8tjjJvMWlFh2OVxx-w",[2781,2785],{"title":2782,"path":2783,"stem":2784,"children":-1},"Replace Excel Solver with Python","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Freplace-excel-solver-with-python","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Freplace-excel-solver-with-python\u002Findex",{"title":2786,"path":2787,"stem":2788,"children":-1},"Running Totals and Year-Over-Year Growth in pandas","\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Frunning-totals-and-year-over-year-growth-in-pandas","advanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas\u002Frunning-totals-and-year-over-year-growth-in-pandas\u002Findex",[2790,2792],{"path":2791,"title":62},"\u002Fadvanced-data-transformation-and-cleaning\u002Fexcel-formula-equivalents-in-pandas",{"path":2793,"title":2767},"\u002Fadvanced-data-transformation-and-cleaning",[],[2796,2799,2802,2805,2808,2811],{"path":2797,"title":2798,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fmerging-and-joining-excel-dataframes\u002Fvlookup-equivalent-in-pandas-for-excel-files","The VLOOKUP Equivalent in pandas for Excel Files",{"path":2800,"title":2801,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fextract-numbers-and-codes-from-text-with-pandas","Extract Numbers and Codes from Text with pandas",{"path":2803,"title":2804,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcleaning-excel-data-with-pandas\u002Fsplit-full-names-into-first-and-last-names-with-pandas","Split Full Names into First and Last Names with pandas",{"path":2806,"title":2807,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fbin-values-into-ranges-with-pandas-cut","Bin Values into Ranges Like Excel FREQUENCY with pd.cut",{"path":2809,"title":2810,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcalculate-percent-of-total-per-group-in-pandas","Calculate Percent of Total per Group in pandas",{"path":2812,"title":2813,"kind":2778},"\u002Fadvanced-data-transformation-and-cleaning\u002Fcreating-pivot-tables-from-excel-data\u002Fcount-distinct-values-per-group-in-pandas","Count Distinct Values per Group in pandas",1790972088512]